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 2126497c311SBarry Smith /* 2136497c311SBarry Smith Returns an array of count items each with a sizeof(eltsize) 2146497c311SBarry Smith */ 2156497c311SBarry Smith static PetscErrorCode GmshBufferGet(GmshFile *gmsh, PetscCount count, size_t eltsize, void *buf) 216d71ae5a4SJacob Faibussowitsch { 217de78e4feSLisandro Dalcin size_t size = count * eltsize; 21811c56cb0SLisandro Dalcin 21911c56cb0SLisandro Dalcin PetscFunctionBegin; 220698a79b9SLisandro Dalcin if (gmsh->wlen < size) { 2219566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->wbuf)); 2229566063dSJacob Faibussowitsch PetscCall(PetscMalloc(size, &gmsh->wbuf)); 223698a79b9SLisandro Dalcin gmsh->wlen = size; 224de78e4feSLisandro Dalcin } 225698a79b9SLisandro Dalcin *(void **)buf = size ? gmsh->wbuf : NULL; 2263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 227de78e4feSLisandro Dalcin } 228de78e4feSLisandro Dalcin 2296497c311SBarry Smith /* 2306497c311SBarry Smith Returns an array of count items each with the size determined by the GmshFile 2316497c311SBarry Smith */ 2326497c311SBarry Smith static PetscErrorCode GmshBufferSizeGet(GmshFile *gmsh, PetscCount count, void *buf) 233d71ae5a4SJacob Faibussowitsch { 234698a79b9SLisandro Dalcin size_t dataSize = (size_t)gmsh->dataSize; 235698a79b9SLisandro Dalcin size_t size = count * dataSize; 236698a79b9SLisandro Dalcin 237698a79b9SLisandro Dalcin PetscFunctionBegin; 238698a79b9SLisandro Dalcin if (gmsh->slen < size) { 2399566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->sbuf)); 2409566063dSJacob Faibussowitsch PetscCall(PetscMalloc(size, &gmsh->sbuf)); 241698a79b9SLisandro Dalcin gmsh->slen = size; 242698a79b9SLisandro Dalcin } 243698a79b9SLisandro Dalcin *(void **)buf = size ? gmsh->sbuf : NULL; 2443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 245698a79b9SLisandro Dalcin } 246698a79b9SLisandro Dalcin 2476497c311SBarry Smith /* 2486497c311SBarry Smith Reads an array of count items each with the size determined by the PetscDataType 2496497c311SBarry Smith */ 2506497c311SBarry Smith static PetscErrorCode GmshRead(GmshFile *gmsh, void *buf, PetscCount count, PetscDataType dtype) 251d71ae5a4SJacob Faibussowitsch { 2526497c311SBarry Smith PetscInt icount; 2536497c311SBarry Smith 254de78e4feSLisandro Dalcin PetscFunctionBegin; 2556497c311SBarry Smith PetscCall(PetscIntCast(count, &icount)); 2566497c311SBarry Smith PetscCall(PetscViewerRead(gmsh->viewer, buf, icount, NULL, dtype)); 2576497c311SBarry Smith if (gmsh->byteSwap) PetscCall(PetscByteSwap(buf, dtype, icount)); 2583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 259698a79b9SLisandro Dalcin } 260698a79b9SLisandro Dalcin 2616497c311SBarry Smith static PetscErrorCode GmshReadString(GmshFile *gmsh, char *buf, PetscCount count) 262d71ae5a4SJacob Faibussowitsch { 2636497c311SBarry Smith PetscInt icount; 2646497c311SBarry Smith 265698a79b9SLisandro Dalcin PetscFunctionBegin; 2666497c311SBarry Smith PetscCall(PetscIntCast(count, &icount)); 2676497c311SBarry Smith PetscCall(PetscViewerRead(gmsh->viewer, buf, icount, NULL, PETSC_STRING)); 2683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 269698a79b9SLisandro Dalcin } 270698a79b9SLisandro Dalcin 271d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshMatch(PETSC_UNUSED GmshFile *gmsh, const char Section[], char line[PETSC_MAX_PATH_LEN], PetscBool *match) 272d71ae5a4SJacob Faibussowitsch { 273d6689ca9SLisandro Dalcin PetscFunctionBegin; 2749566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(line, Section, match)); 2753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 276d6689ca9SLisandro Dalcin } 277d6689ca9SLisandro Dalcin 278d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshExpect(GmshFile *gmsh, const char Section[], char line[PETSC_MAX_PATH_LEN]) 279d71ae5a4SJacob Faibussowitsch { 280d6689ca9SLisandro Dalcin PetscBool match; 281d6689ca9SLisandro Dalcin 282d6689ca9SLisandro Dalcin PetscFunctionBegin; 2839566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, Section, line, &match)); 28400045ab3SPierre Jolivet PetscCheck(match, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file, expecting %s, not %s", Section, line); 2853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 286d6689ca9SLisandro Dalcin } 287d6689ca9SLisandro Dalcin 288d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadSection(GmshFile *gmsh, char line[PETSC_MAX_PATH_LEN]) 289d71ae5a4SJacob Faibussowitsch { 290d6689ca9SLisandro Dalcin PetscBool match; 291d6689ca9SLisandro Dalcin 292d6689ca9SLisandro Dalcin PetscFunctionBegin; 293d6689ca9SLisandro Dalcin while (PETSC_TRUE) { 2949566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 1)); 2959566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, "$Comments", line, &match)); 296d6689ca9SLisandro Dalcin if (!match) break; 297d6689ca9SLisandro Dalcin while (PETSC_TRUE) { 2989566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 1)); 2999566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, "$EndComments", line, &match)); 300d6689ca9SLisandro Dalcin if (match) break; 301d6689ca9SLisandro Dalcin } 302d6689ca9SLisandro Dalcin } 3033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 304d6689ca9SLisandro Dalcin } 305d6689ca9SLisandro Dalcin 306d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEndSection(GmshFile *gmsh, const char EndSection[], char line[PETSC_MAX_PATH_LEN]) 307d71ae5a4SJacob Faibussowitsch { 308d6689ca9SLisandro Dalcin PetscFunctionBegin; 3099566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 1)); 3109566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, EndSection, line)); 3113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 312d6689ca9SLisandro Dalcin } 313d6689ca9SLisandro Dalcin 3146497c311SBarry Smith /* 3156497c311SBarry Smith Read into buf[] count number of PetscInt integers (the file storage size may be different than PetscInt) 3166497c311SBarry Smith */ 3176497c311SBarry Smith static PetscErrorCode GmshReadPetscInt(GmshFile *gmsh, PetscInt *buf, PetscCount count) 318d71ae5a4SJacob Faibussowitsch { 3196497c311SBarry Smith PetscCount i; 320698a79b9SLisandro Dalcin size_t dataSize = (size_t)gmsh->dataSize; 321698a79b9SLisandro Dalcin 322698a79b9SLisandro Dalcin PetscFunctionBegin; 323698a79b9SLisandro Dalcin if (dataSize == sizeof(PetscInt)) { 3249566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, buf, count, PETSC_INT)); 325698a79b9SLisandro Dalcin } else if (dataSize == sizeof(int)) { 326698a79b9SLisandro Dalcin int *ibuf = NULL; 3279566063dSJacob Faibussowitsch PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf)); 3289566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, ibuf, count, PETSC_ENUM)); 329698a79b9SLisandro Dalcin for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i]; 330698a79b9SLisandro Dalcin } else if (dataSize == sizeof(long)) { 331698a79b9SLisandro Dalcin long *ibuf = NULL; 3329566063dSJacob Faibussowitsch PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf)); 3339566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, ibuf, count, PETSC_LONG)); 334698a79b9SLisandro Dalcin for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i]; 335698a79b9SLisandro Dalcin } else if (dataSize == sizeof(PetscInt64)) { 336698a79b9SLisandro Dalcin PetscInt64 *ibuf = NULL; 3379566063dSJacob Faibussowitsch PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf)); 3389566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, ibuf, count, PETSC_INT64)); 339698a79b9SLisandro Dalcin for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i]; 340698a79b9SLisandro Dalcin } 3413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 342698a79b9SLisandro Dalcin } 343698a79b9SLisandro Dalcin 3446497c311SBarry Smith /* 3456497c311SBarry Smith Read into buf[] count number of PetscCount integers (the file storage size may be different than PetscCount) 3466497c311SBarry Smith */ 3476497c311SBarry Smith static PetscErrorCode GmshReadPetscCount(GmshFile *gmsh, PetscCount *buf, PetscCount count) 3486497c311SBarry Smith { 3496497c311SBarry Smith PetscCount i; 3506497c311SBarry Smith size_t dataSize = (size_t)gmsh->dataSize; 3516497c311SBarry Smith 3526497c311SBarry Smith PetscFunctionBegin; 3536497c311SBarry Smith if (dataSize == sizeof(PetscCount)) { 3546497c311SBarry Smith PetscCall(GmshRead(gmsh, buf, count, PETSC_COUNT)); 3556497c311SBarry Smith } else if (dataSize == sizeof(int)) { 3566497c311SBarry Smith int *ibuf = NULL; 3576497c311SBarry Smith PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf)); 3586497c311SBarry Smith PetscCall(GmshRead(gmsh, ibuf, count, PETSC_ENUM)); 3596497c311SBarry Smith for (i = 0; i < count; ++i) buf[i] = (PetscCount)ibuf[i]; 3606497c311SBarry Smith } else if (dataSize == sizeof(long)) { 3616497c311SBarry Smith long *ibuf = NULL; 3626497c311SBarry Smith PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf)); 3636497c311SBarry Smith PetscCall(GmshRead(gmsh, ibuf, count, PETSC_LONG)); 3646497c311SBarry Smith for (i = 0; i < count; ++i) buf[i] = (PetscCount)ibuf[i]; 3656497c311SBarry Smith } else if (dataSize == sizeof(PetscInt64)) { 3666497c311SBarry Smith PetscInt64 *ibuf = NULL; 3676497c311SBarry Smith PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf)); 3686497c311SBarry Smith PetscCall(GmshRead(gmsh, ibuf, count, PETSC_INT64)); 3696497c311SBarry Smith for (i = 0; i < count; ++i) buf[i] = (PetscCount)ibuf[i]; 3706497c311SBarry Smith } 3716497c311SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 3726497c311SBarry Smith } 3736497c311SBarry Smith 3746497c311SBarry Smith /* 3756497c311SBarry Smith Read into buf[] count number of PetscEnum integers 3766497c311SBarry Smith */ 3776497c311SBarry Smith static PetscErrorCode GmshReadInt(GmshFile *gmsh, int *buf, PetscCount count) 378d71ae5a4SJacob Faibussowitsch { 379698a79b9SLisandro Dalcin PetscFunctionBegin; 3809566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, buf, count, PETSC_ENUM)); 3813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 382698a79b9SLisandro Dalcin } 383698a79b9SLisandro Dalcin 3846497c311SBarry Smith /* 3856497c311SBarry Smith Read into buf[] count number of double 3866497c311SBarry Smith */ 3876497c311SBarry Smith static PetscErrorCode GmshReadDouble(GmshFile *gmsh, double *buf, PetscCount count) 388d71ae5a4SJacob Faibussowitsch { 389698a79b9SLisandro Dalcin PetscFunctionBegin; 3909566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, buf, count, PETSC_DOUBLE)); 3913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 392de78e4feSLisandro Dalcin } 393de78e4feSLisandro Dalcin 3949c0edc59SMatthew G. Knepley #define GMSH_MAX_TAGS 16 3957d5b9244SMatthew G. Knepley 396de78e4feSLisandro Dalcin typedef struct { 3970598e1a2SLisandro Dalcin PetscInt id; /* Entity ID */ 3980598e1a2SLisandro Dalcin PetscInt dim; /* Dimension */ 399de78e4feSLisandro Dalcin double bbox[6]; /* Bounding box */ 400de78e4feSLisandro Dalcin PetscInt numTags; /* Size of tag array */ 4017d5b9244SMatthew G. Knepley int tags[GMSH_MAX_TAGS]; /* Tag array */ 402de78e4feSLisandro Dalcin } GmshEntity; 403de78e4feSLisandro Dalcin 404de78e4feSLisandro Dalcin typedef struct { 405730356f6SLisandro Dalcin GmshEntity *entity[4]; 406730356f6SLisandro Dalcin PetscHMapI entityMap[4]; 407730356f6SLisandro Dalcin } GmshEntities; 408730356f6SLisandro Dalcin 4096497c311SBarry Smith static PetscErrorCode GmshEntitiesCreate(PetscCount count[4], GmshEntities **entities) 410d71ae5a4SJacob Faibussowitsch { 411730356f6SLisandro Dalcin PetscFunctionBegin; 4129566063dSJacob Faibussowitsch PetscCall(PetscNew(entities)); 4136497c311SBarry Smith for (PetscInt dim = 0; dim < 4; ++dim) { 4149566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(count[dim], &(*entities)->entity[dim])); 4159566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&(*entities)->entityMap[dim])); 416730356f6SLisandro Dalcin } 4173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 418730356f6SLisandro Dalcin } 419730356f6SLisandro Dalcin 420d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshEntitiesDestroy(GmshEntities **entities) 421d71ae5a4SJacob Faibussowitsch { 4220598e1a2SLisandro Dalcin PetscInt dim; 4230598e1a2SLisandro Dalcin 4240598e1a2SLisandro Dalcin PetscFunctionBegin; 4253ba16761SJacob Faibussowitsch if (!*entities) PetscFunctionReturn(PETSC_SUCCESS); 4260598e1a2SLisandro Dalcin for (dim = 0; dim < 4; ++dim) { 4279566063dSJacob Faibussowitsch PetscCall(PetscFree((*entities)->entity[dim])); 4289566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&(*entities)->entityMap[dim])); 4290598e1a2SLisandro Dalcin } 430f4f49eeaSPierre Jolivet PetscCall(PetscFree(*entities)); 4313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4320598e1a2SLisandro Dalcin } 4330598e1a2SLisandro Dalcin 434d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshEntitiesAdd(GmshEntities *entities, PetscInt index, PetscInt dim, PetscInt eid, GmshEntity **entity) 435d71ae5a4SJacob Faibussowitsch { 436730356f6SLisandro Dalcin PetscFunctionBegin; 4379566063dSJacob Faibussowitsch PetscCall(PetscHMapISet(entities->entityMap[dim], eid, index)); 438730356f6SLisandro Dalcin entities->entity[dim][index].dim = dim; 439730356f6SLisandro Dalcin entities->entity[dim][index].id = eid; 440730356f6SLisandro Dalcin if (entity) *entity = &entities->entity[dim][index]; 4413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 442730356f6SLisandro Dalcin } 443730356f6SLisandro Dalcin 444d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshEntitiesGet(GmshEntities *entities, PetscInt dim, PetscInt eid, GmshEntity **entity) 445d71ae5a4SJacob Faibussowitsch { 446730356f6SLisandro Dalcin PetscInt index; 447730356f6SLisandro Dalcin 448730356f6SLisandro Dalcin PetscFunctionBegin; 4499566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(entities->entityMap[dim], eid, &index)); 450730356f6SLisandro Dalcin *entity = &entities->entity[dim][index]; 4513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 452730356f6SLisandro Dalcin } 453730356f6SLisandro Dalcin 4540598e1a2SLisandro Dalcin typedef struct { 4550598e1a2SLisandro Dalcin PetscInt *id; /* Node IDs */ 4560598e1a2SLisandro Dalcin double *xyz; /* Coordinates */ 45781a1af93SMatthew G. Knepley PetscInt *tag; /* Physical tag */ 4580598e1a2SLisandro Dalcin } GmshNodes; 4590598e1a2SLisandro Dalcin 4606497c311SBarry Smith static PetscErrorCode GmshNodesCreate(PetscCount count, GmshNodes **nodes) 461d71ae5a4SJacob Faibussowitsch { 462730356f6SLisandro Dalcin PetscFunctionBegin; 4639566063dSJacob Faibussowitsch PetscCall(PetscNew(nodes)); 4649566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(count * 1, &(*nodes)->id)); 4659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(count * 3, &(*nodes)->xyz)); 4667d5b9244SMatthew G. Knepley PetscCall(PetscMalloc1(count * GMSH_MAX_TAGS, &(*nodes)->tag)); 4673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 468730356f6SLisandro Dalcin } 4690598e1a2SLisandro Dalcin 470d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshNodesDestroy(GmshNodes **nodes) 471d71ae5a4SJacob Faibussowitsch { 4720598e1a2SLisandro Dalcin PetscFunctionBegin; 4733ba16761SJacob Faibussowitsch if (!*nodes) PetscFunctionReturn(PETSC_SUCCESS); 4749566063dSJacob Faibussowitsch PetscCall(PetscFree((*nodes)->id)); 4759566063dSJacob Faibussowitsch PetscCall(PetscFree((*nodes)->xyz)); 4769566063dSJacob Faibussowitsch PetscCall(PetscFree((*nodes)->tag)); 477f4f49eeaSPierre Jolivet PetscCall(PetscFree(*nodes)); 4783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 479730356f6SLisandro Dalcin } 480730356f6SLisandro Dalcin 481730356f6SLisandro Dalcin typedef struct { 4820598e1a2SLisandro Dalcin PetscInt id; /* Element ID */ 4830598e1a2SLisandro Dalcin PetscInt dim; /* Dimension */ 484de78e4feSLisandro Dalcin PetscInt cellType; /* Cell type */ 4850598e1a2SLisandro Dalcin PetscInt numVerts; /* Size of vertex array */ 486de78e4feSLisandro Dalcin PetscInt numNodes; /* Size of node array */ 4870598e1a2SLisandro Dalcin PetscInt *nodes; /* Vertex/Node array */ 48881a1af93SMatthew G. Knepley PetscInt numTags; /* Size of physical tag array */ 4897d5b9244SMatthew G. Knepley int tags[GMSH_MAX_TAGS]; /* Physical tag array */ 490de78e4feSLisandro Dalcin } GmshElement; 491de78e4feSLisandro Dalcin 4926497c311SBarry Smith static PetscErrorCode GmshElementsCreate(PetscCount count, GmshElement **elements) 493d71ae5a4SJacob Faibussowitsch { 4940598e1a2SLisandro Dalcin PetscFunctionBegin; 4959566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(count, elements)); 4963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4970598e1a2SLisandro Dalcin } 4980598e1a2SLisandro Dalcin 499d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshElementsDestroy(GmshElement **elements) 500d71ae5a4SJacob Faibussowitsch { 5010598e1a2SLisandro Dalcin PetscFunctionBegin; 5023ba16761SJacob Faibussowitsch if (!*elements) PetscFunctionReturn(PETSC_SUCCESS); 5039566063dSJacob Faibussowitsch PetscCall(PetscFree(*elements)); 5043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5050598e1a2SLisandro Dalcin } 5060598e1a2SLisandro Dalcin 5070598e1a2SLisandro Dalcin typedef struct { 5080598e1a2SLisandro Dalcin PetscInt dim; 509066ea43fSLisandro Dalcin PetscInt order; 5100598e1a2SLisandro Dalcin GmshEntities *entities; 5110598e1a2SLisandro Dalcin PetscInt numNodes; 5120598e1a2SLisandro Dalcin GmshNodes *nodelist; 5130598e1a2SLisandro Dalcin PetscInt numElems; 5140598e1a2SLisandro Dalcin GmshElement *elements; 5150598e1a2SLisandro Dalcin PetscInt numVerts; 5160598e1a2SLisandro Dalcin PetscInt numCells; 5170598e1a2SLisandro Dalcin PetscInt *periodMap; 5180598e1a2SLisandro Dalcin PetscInt *vertexMap; 5190598e1a2SLisandro Dalcin PetscSegBuffer segbuf; 520a45dabc8SMatthew G. Knepley PetscInt numRegions; 52190d778b8SLisandro Dalcin PetscInt *regionDims; 522a45dabc8SMatthew G. Knepley PetscInt *regionTags; 523a45dabc8SMatthew G. Knepley char **regionNames; 5240598e1a2SLisandro Dalcin } GmshMesh; 5250598e1a2SLisandro Dalcin 526d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshMeshCreate(GmshMesh **mesh) 527d71ae5a4SJacob Faibussowitsch { 5280598e1a2SLisandro Dalcin PetscFunctionBegin; 5299566063dSJacob Faibussowitsch PetscCall(PetscNew(mesh)); 5309566063dSJacob Faibussowitsch PetscCall(PetscSegBufferCreate(sizeof(PetscInt), 0, &(*mesh)->segbuf)); 5313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5320598e1a2SLisandro Dalcin } 5330598e1a2SLisandro Dalcin 534d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshMeshDestroy(GmshMesh **mesh) 535d71ae5a4SJacob Faibussowitsch { 536a45dabc8SMatthew G. Knepley PetscInt r; 5370598e1a2SLisandro Dalcin 5380598e1a2SLisandro Dalcin PetscFunctionBegin; 5393ba16761SJacob Faibussowitsch if (!*mesh) PetscFunctionReturn(PETSC_SUCCESS); 5409566063dSJacob Faibussowitsch PetscCall(GmshEntitiesDestroy(&(*mesh)->entities)); 5419566063dSJacob Faibussowitsch PetscCall(GmshNodesDestroy(&(*mesh)->nodelist)); 5429566063dSJacob Faibussowitsch PetscCall(GmshElementsDestroy(&(*mesh)->elements)); 5439566063dSJacob Faibussowitsch PetscCall(PetscFree((*mesh)->periodMap)); 5449566063dSJacob Faibussowitsch PetscCall(PetscFree((*mesh)->vertexMap)); 5459566063dSJacob Faibussowitsch PetscCall(PetscSegBufferDestroy(&(*mesh)->segbuf)); 5469566063dSJacob Faibussowitsch for (r = 0; r < (*mesh)->numRegions; ++r) PetscCall(PetscFree((*mesh)->regionNames[r])); 54790d778b8SLisandro Dalcin PetscCall(PetscFree3((*mesh)->regionDims, (*mesh)->regionTags, (*mesh)->regionNames)); 548f4f49eeaSPierre Jolivet PetscCall(PetscFree(*mesh)); 5493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5500598e1a2SLisandro Dalcin } 5510598e1a2SLisandro Dalcin 552d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes_v22(GmshFile *gmsh, GmshMesh *mesh) 553d71ae5a4SJacob Faibussowitsch { 554698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 555698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 556de78e4feSLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 5577d5b9244SMatthew G. Knepley int n, t, num, nid, snum; 5580598e1a2SLisandro Dalcin GmshNodes *nodes; 559de78e4feSLisandro Dalcin 560de78e4feSLisandro Dalcin PetscFunctionBegin; 5619566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 562698a79b9SLisandro Dalcin snum = sscanf(line, "%d", &num); 56308401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 5649566063dSJacob Faibussowitsch PetscCall(GmshNodesCreate(num, &nodes)); 5650598e1a2SLisandro Dalcin mesh->numNodes = num; 5660598e1a2SLisandro Dalcin mesh->nodelist = nodes; 5670598e1a2SLisandro Dalcin for (n = 0; n < num; ++n) { 5680598e1a2SLisandro Dalcin double *xyz = nodes->xyz + n * 3; 5699566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM)); 5709566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE)); 5719566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nid, PETSC_ENUM, 1)); 5729566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(xyz, PETSC_DOUBLE, 3)); 5730598e1a2SLisandro Dalcin nodes->id[n] = nid; 5747d5b9244SMatthew G. Knepley for (t = 0; t < GMSH_MAX_TAGS; ++t) nodes->tag[n * GMSH_MAX_TAGS + t] = -1; 57511c56cb0SLisandro Dalcin } 5763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 57711c56cb0SLisandro Dalcin } 57811c56cb0SLisandro Dalcin 579de78e4feSLisandro Dalcin /* Gmsh elements can be of any dimension/co-dimension, so we need to traverse the 580de78e4feSLisandro Dalcin file contents multiple times to figure out the true number of cells and facets 581de78e4feSLisandro Dalcin in the given mesh. To make this more efficient we read the file contents only 582de78e4feSLisandro Dalcin once and store them in memory, while determining the true number of cells. */ 583d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements_v22(GmshFile *gmsh, GmshMesh *mesh) 584d71ae5a4SJacob Faibussowitsch { 585698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 586698a79b9SLisandro Dalcin PetscBool binary = gmsh->binary; 587698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 588de78e4feSLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 5890598e1a2SLisandro Dalcin int i, c, p, num, ibuf[1 + 4 + 1000], snum; 5900598e1a2SLisandro Dalcin int cellType, numElem, numVerts, numNodes, numTags; 591df032b82SMatthew G. Knepley GmshElement *elements; 5920598e1a2SLisandro Dalcin PetscInt *nodeMap = gmsh->nodeMap; 593df032b82SMatthew G. Knepley 594df032b82SMatthew G. Knepley PetscFunctionBegin; 5959566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 596698a79b9SLisandro Dalcin snum = sscanf(line, "%d", &num); 59708401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 5989566063dSJacob Faibussowitsch PetscCall(GmshElementsCreate(num, &elements)); 5990598e1a2SLisandro Dalcin mesh->numElems = num; 6000598e1a2SLisandro Dalcin mesh->elements = elements; 601698a79b9SLisandro Dalcin for (c = 0; c < num;) { 6029566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM)); 6039566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, 3)); 6040598e1a2SLisandro Dalcin 6050598e1a2SLisandro Dalcin cellType = binary ? ibuf[0] : ibuf[1]; 6060598e1a2SLisandro Dalcin numElem = binary ? ibuf[1] : 1; 607df032b82SMatthew G. Knepley numTags = ibuf[2]; 6080598e1a2SLisandro Dalcin 6099566063dSJacob Faibussowitsch PetscCall(GmshCellTypeCheck(cellType)); 6100598e1a2SLisandro Dalcin numVerts = GmshCellMap[cellType].numVerts; 6110598e1a2SLisandro Dalcin numNodes = GmshCellMap[cellType].numNodes; 6120598e1a2SLisandro Dalcin 613df032b82SMatthew G. Knepley for (i = 0; i < numElem; ++i, ++c) { 6140598e1a2SLisandro Dalcin GmshElement *element = elements + c; 6150598e1a2SLisandro Dalcin const int off = binary ? 0 : 1, nint = 1 + numTags + numNodes - off; 6160598e1a2SLisandro Dalcin const int *id = ibuf, *nodes = ibuf + 1 + numTags, *tags = ibuf + 1; 6179566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf + off, nint, NULL, PETSC_ENUM)); 6189566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf + off, PETSC_ENUM, nint)); 6190598e1a2SLisandro Dalcin element->id = id[0]; 6200598e1a2SLisandro Dalcin element->dim = GmshCellMap[cellType].dim; 6210598e1a2SLisandro Dalcin element->cellType = cellType; 6220598e1a2SLisandro Dalcin element->numVerts = numVerts; 6230598e1a2SLisandro Dalcin element->numNodes = numNodes; 6247d5b9244SMatthew G. Knepley element->numTags = PetscMin(numTags, GMSH_MAX_TAGS); 6259566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes)); 6260598e1a2SLisandro Dalcin for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]]; 6270598e1a2SLisandro Dalcin for (p = 0; p < element->numTags; p++) element->tags[p] = tags[p]; 628df032b82SMatthew G. Knepley } 629df032b82SMatthew G. Knepley } 6303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 631df032b82SMatthew G. Knepley } 6327d282ae0SMichael Lange 633de78e4feSLisandro Dalcin /* 634de78e4feSLisandro Dalcin $Entities 635de78e4feSLisandro Dalcin numPoints(unsigned long) numCurves(unsigned long) 636de78e4feSLisandro Dalcin numSurfaces(unsigned long) numVolumes(unsigned long) 637de78e4feSLisandro Dalcin // points 638de78e4feSLisandro Dalcin tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 639de78e4feSLisandro Dalcin boxMaxX(double) boxMaxY(double) boxMaxZ(double) 640de78e4feSLisandro Dalcin numPhysicals(unsigned long) phyisicalTag[...](int) 641de78e4feSLisandro Dalcin ... 642de78e4feSLisandro Dalcin // curves 643de78e4feSLisandro Dalcin tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 644de78e4feSLisandro Dalcin boxMaxX(double) boxMaxY(double) boxMaxZ(double) 645de78e4feSLisandro Dalcin numPhysicals(unsigned long) physicalTag[...](int) 646de78e4feSLisandro Dalcin numBREPVert(unsigned long) tagBREPVert[...](int) 647de78e4feSLisandro Dalcin ... 648de78e4feSLisandro Dalcin // surfaces 649de78e4feSLisandro Dalcin tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 650de78e4feSLisandro Dalcin boxMaxX(double) boxMaxY(double) boxMaxZ(double) 651de78e4feSLisandro Dalcin numPhysicals(unsigned long) physicalTag[...](int) 652de78e4feSLisandro Dalcin numBREPCurve(unsigned long) tagBREPCurve[...](int) 653de78e4feSLisandro Dalcin ... 654de78e4feSLisandro Dalcin // volumes 655de78e4feSLisandro Dalcin tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 656de78e4feSLisandro Dalcin boxMaxX(double) boxMaxY(double) boxMaxZ(double) 657de78e4feSLisandro Dalcin numPhysicals(unsigned long) physicalTag[...](int) 658de78e4feSLisandro Dalcin numBREPSurfaces(unsigned long) tagBREPSurfaces[...](int) 659de78e4feSLisandro Dalcin ... 660de78e4feSLisandro Dalcin $EndEntities 661de78e4feSLisandro Dalcin */ 662d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEntities_v40(GmshFile *gmsh, GmshMesh *mesh) 663d71ae5a4SJacob Faibussowitsch { 664698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 665698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 6666497c311SBarry Smith long lnum, lbuf[4]; 667730356f6SLisandro Dalcin int dim, eid, numTags, *ibuf, t; 6686497c311SBarry Smith PetscCount index, count[4]; 6696497c311SBarry Smith PetscInt i, num; 670a5ba3d71SLisandro Dalcin GmshEntity *entity = NULL; 671de78e4feSLisandro Dalcin 672de78e4feSLisandro Dalcin PetscFunctionBegin; 6739566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, lbuf, 4, NULL, PETSC_LONG)); 6749566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(lbuf, PETSC_LONG, 4)); 6756497c311SBarry Smith for (i = 0; i < 4; ++i) count[i] = (PetscCount)lbuf[i]; 6769566063dSJacob Faibussowitsch PetscCall(GmshEntitiesCreate(count, &mesh->entities)); 677de78e4feSLisandro Dalcin for (dim = 0; dim < 4; ++dim) { 678730356f6SLisandro Dalcin for (index = 0; index < count[dim]; ++index) { 6799566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &eid, 1, NULL, PETSC_ENUM)); 6809566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&eid, PETSC_ENUM, 1)); 6819566063dSJacob Faibussowitsch PetscCall(GmshEntitiesAdd(mesh->entities, (PetscInt)index, dim, eid, &entity)); 6829566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, entity->bbox, 6, NULL, PETSC_DOUBLE)); 6839566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(entity->bbox, PETSC_DOUBLE, 6)); 6846497c311SBarry Smith PetscCall(PetscViewerRead(viewer, &lnum, 1, NULL, PETSC_LONG)); 6856497c311SBarry Smith if (byteSwap) PetscCall(PetscByteSwap(&lnum, PETSC_LONG, 1)); 6866497c311SBarry Smith PetscCall(PetscIntCast(lnum, &num)); 6879566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, num, sizeof(int), &ibuf)); 6889566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, num, NULL, PETSC_ENUM)); 6899566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, num)); 6907d5b9244SMatthew G. Knepley entity->numTags = numTags = (int)PetscMin(num, GMSH_MAX_TAGS); 691de78e4feSLisandro Dalcin for (t = 0; t < numTags; ++t) entity->tags[t] = ibuf[t]; 692de78e4feSLisandro Dalcin if (dim == 0) continue; 6936497c311SBarry Smith PetscCall(PetscViewerRead(viewer, &lnum, 1, NULL, PETSC_LONG)); 6946497c311SBarry Smith if (byteSwap) PetscCall(PetscByteSwap(&lnum, PETSC_LONG, 1)); 6956497c311SBarry Smith PetscCall(GmshBufferGet(gmsh, lnum, sizeof(int), &ibuf)); 6966497c311SBarry Smith PetscCall(PetscIntCast(lnum, &num)); 6979566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, num, NULL, PETSC_ENUM)); 6989566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, num)); 699de78e4feSLisandro Dalcin } 700de78e4feSLisandro Dalcin } 7013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 702de78e4feSLisandro Dalcin } 703de78e4feSLisandro Dalcin 704de78e4feSLisandro Dalcin /* 705de78e4feSLisandro Dalcin $Nodes 706de78e4feSLisandro Dalcin numEntityBlocks(unsigned long) numNodes(unsigned long) 707de78e4feSLisandro Dalcin tagEntity(int) dimEntity(int) typeNode(int) numNodes(unsigned long) 708de78e4feSLisandro Dalcin tag(int) x(double) y(double) z(double) 709de78e4feSLisandro Dalcin ... 710de78e4feSLisandro Dalcin ... 711de78e4feSLisandro Dalcin $EndNodes 712de78e4feSLisandro Dalcin */ 713d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes_v40(GmshFile *gmsh, GmshMesh *mesh) 714d71ae5a4SJacob Faibussowitsch { 715698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 716698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 7177d5b9244SMatthew G. Knepley long block, node, n, t, numEntityBlocks, numTotalNodes, numNodes; 718de78e4feSLisandro Dalcin int info[3], nid; 7190598e1a2SLisandro Dalcin GmshNodes *nodes; 720de78e4feSLisandro Dalcin 721de78e4feSLisandro Dalcin PetscFunctionBegin; 7229566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numEntityBlocks, 1, NULL, PETSC_LONG)); 7239566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numEntityBlocks, PETSC_LONG, 1)); 7249566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numTotalNodes, 1, NULL, PETSC_LONG)); 7259566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numTotalNodes, PETSC_LONG, 1)); 7269566063dSJacob Faibussowitsch PetscCall(GmshNodesCreate(numTotalNodes, &nodes)); 7276497c311SBarry Smith PetscCall(PetscIntCast(numTotalNodes, &mesh->numNodes)); 7280598e1a2SLisandro Dalcin mesh->nodelist = nodes; 7290598e1a2SLisandro Dalcin for (n = 0, block = 0; block < numEntityBlocks; ++block) { 7309566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, info, 3, NULL, PETSC_ENUM)); 7319566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numNodes, 1, NULL, PETSC_LONG)); 7329566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numNodes, PETSC_LONG, 1)); 733698a79b9SLisandro Dalcin if (gmsh->binary) { 734277f51e8SBarry Smith size_t nbytes = sizeof(int) + 3 * sizeof(double); 735da81f932SPierre Jolivet char *cbuf = NULL; /* dummy value to prevent warning from compiler about possible uninitialized value */ 7366497c311SBarry Smith PetscInt icnt; 7376497c311SBarry Smith 7389566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, numNodes, nbytes, &cbuf)); 7396497c311SBarry Smith PetscCall(PetscIntCast(numNodes * nbytes, &icnt)); 7406497c311SBarry Smith PetscCall(PetscViewerRead(viewer, cbuf, icnt, NULL, PETSC_CHAR)); 7410598e1a2SLisandro Dalcin for (node = 0; node < numNodes; ++node, ++n) { 742de78e4feSLisandro Dalcin char *cnid = cbuf + node * nbytes, *cxyz = cnid + sizeof(int); 7430598e1a2SLisandro Dalcin double *xyz = nodes->xyz + n * 3; 7446497c311SBarry Smith 7459566063dSJacob Faibussowitsch if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(cnid, PETSC_ENUM, 1)); 7469566063dSJacob Faibussowitsch if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(cxyz, PETSC_DOUBLE, 3)); 7479566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(&nid, cnid, sizeof(int))); 7489566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(xyz, cxyz, 3 * sizeof(double))); 7499566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nid, PETSC_ENUM, 1)); 7509566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(xyz, PETSC_DOUBLE, 3)); 7510598e1a2SLisandro Dalcin nodes->id[n] = nid; 7527d5b9244SMatthew G. Knepley for (t = 0; t < GMSH_MAX_TAGS; ++t) nodes->tag[n * GMSH_MAX_TAGS + t] = -1; 753de78e4feSLisandro Dalcin } 754de78e4feSLisandro Dalcin } else { 7550598e1a2SLisandro Dalcin for (node = 0; node < numNodes; ++node, ++n) { 7560598e1a2SLisandro Dalcin double *xyz = nodes->xyz + n * 3; 7576497c311SBarry Smith 7589566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM)); 7599566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE)); 7609566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nid, PETSC_ENUM, 1)); 7619566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(xyz, PETSC_DOUBLE, 3)); 7620598e1a2SLisandro Dalcin nodes->id[n] = nid; 7637d5b9244SMatthew G. Knepley for (t = 0; t < GMSH_MAX_TAGS; ++t) nodes->tag[n * GMSH_MAX_TAGS + t] = -1; 764de78e4feSLisandro Dalcin } 765de78e4feSLisandro Dalcin } 766de78e4feSLisandro Dalcin } 7673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 768de78e4feSLisandro Dalcin } 769de78e4feSLisandro Dalcin 770de78e4feSLisandro Dalcin /* 771de78e4feSLisandro Dalcin $Elements 772de78e4feSLisandro Dalcin numEntityBlocks(unsigned long) numElements(unsigned long) 773de78e4feSLisandro Dalcin tagEntity(int) dimEntity(int) typeEle(int) numElements(unsigned long) 774de78e4feSLisandro Dalcin tag(int) numVert[...](int) 775de78e4feSLisandro Dalcin ... 776de78e4feSLisandro Dalcin ... 777de78e4feSLisandro Dalcin $EndElements 778de78e4feSLisandro Dalcin */ 779d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements_v40(GmshFile *gmsh, GmshMesh *mesh) 780d71ae5a4SJacob Faibussowitsch { 781698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 782698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 783de78e4feSLisandro Dalcin long c, block, numEntityBlocks, numTotalElements, elem, numElements; 784de78e4feSLisandro Dalcin int p, info[3], *ibuf = NULL; 7850598e1a2SLisandro Dalcin int eid, dim, cellType, numVerts, numNodes, numTags; 786a5ba3d71SLisandro Dalcin GmshEntity *entity = NULL; 787de78e4feSLisandro Dalcin GmshElement *elements; 7886497c311SBarry Smith PetscInt *nodeMap = gmsh->nodeMap, icnt; 789de78e4feSLisandro Dalcin 790de78e4feSLisandro Dalcin PetscFunctionBegin; 7919566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numEntityBlocks, 1, NULL, PETSC_LONG)); 7929566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numEntityBlocks, PETSC_LONG, 1)); 7939566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numTotalElements, 1, NULL, PETSC_LONG)); 7949566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numTotalElements, PETSC_LONG, 1)); 7959566063dSJacob Faibussowitsch PetscCall(GmshElementsCreate(numTotalElements, &elements)); 7966497c311SBarry Smith PetscCall(PetscIntCast(numTotalElements, &mesh->numElems)); 7970598e1a2SLisandro Dalcin mesh->elements = elements; 798de78e4feSLisandro Dalcin for (c = 0, block = 0; block < numEntityBlocks; ++block) { 7999566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, info, 3, NULL, PETSC_ENUM)); 8009566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(info, PETSC_ENUM, 3)); 8019371c9d4SSatish Balay eid = info[0]; 8029371c9d4SSatish Balay dim = info[1]; 8039371c9d4SSatish Balay cellType = info[2]; 8049566063dSJacob Faibussowitsch PetscCall(GmshEntitiesGet(mesh->entities, dim, eid, &entity)); 8059566063dSJacob Faibussowitsch PetscCall(GmshCellTypeCheck(cellType)); 8060598e1a2SLisandro Dalcin numVerts = GmshCellMap[cellType].numVerts; 8070598e1a2SLisandro Dalcin numNodes = GmshCellMap[cellType].numNodes; 8086497c311SBarry Smith numTags = (int)entity->numTags; 8099566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numElements, 1, NULL, PETSC_LONG)); 8109566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numElements, PETSC_LONG, 1)); 8119566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, (1 + numNodes) * numElements, sizeof(int), &ibuf)); 8126497c311SBarry Smith PetscCall(PetscIntCast((1 + numNodes) * numElements, &icnt)); 8136497c311SBarry Smith PetscCall(PetscViewerRead(viewer, ibuf, icnt, NULL, PETSC_ENUM)); 8149566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, (1 + numNodes) * numElements)); 815de78e4feSLisandro Dalcin for (elem = 0; elem < numElements; ++elem, ++c) { 816de78e4feSLisandro Dalcin GmshElement *element = elements + c; 8170598e1a2SLisandro Dalcin const int *id = ibuf + elem * (1 + numNodes), *nodes = id + 1; 8180598e1a2SLisandro Dalcin element->id = id[0]; 819de78e4feSLisandro Dalcin element->dim = dim; 820de78e4feSLisandro Dalcin element->cellType = cellType; 8210598e1a2SLisandro Dalcin element->numVerts = numVerts; 822de78e4feSLisandro Dalcin element->numNodes = numNodes; 823de78e4feSLisandro Dalcin element->numTags = numTags; 8249566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes)); 8250598e1a2SLisandro Dalcin for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]]; 8260598e1a2SLisandro Dalcin for (p = 0; p < element->numTags; p++) element->tags[p] = entity->tags[p]; 827de78e4feSLisandro Dalcin } 828de78e4feSLisandro Dalcin } 8293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 830698a79b9SLisandro Dalcin } 831698a79b9SLisandro Dalcin 832d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPeriodic_v40(GmshFile *gmsh, PetscInt periodicMap[]) 833d71ae5a4SJacob Faibussowitsch { 834698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 835698a79b9SLisandro Dalcin int fileFormat = gmsh->fileFormat; 836698a79b9SLisandro Dalcin PetscBool binary = gmsh->binary; 837698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 838698a79b9SLisandro Dalcin int numPeriodic, snum, i; 839698a79b9SLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 8400598e1a2SLisandro Dalcin PetscInt *nodeMap = gmsh->nodeMap; 841698a79b9SLisandro Dalcin 842698a79b9SLisandro Dalcin PetscFunctionBegin; 843698a79b9SLisandro Dalcin if (fileFormat == 22 || !binary) { 8449566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 845698a79b9SLisandro Dalcin snum = sscanf(line, "%d", &numPeriodic); 84608401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 847698a79b9SLisandro Dalcin } else { 8489566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numPeriodic, 1, NULL, PETSC_ENUM)); 8499566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numPeriodic, PETSC_ENUM, 1)); 850698a79b9SLisandro Dalcin } 851698a79b9SLisandro Dalcin for (i = 0; i < numPeriodic; i++) { 8529dddd249SSatish Balay int ibuf[3], correspondingDim = -1, correspondingTag = -1, primaryTag = -1, correspondingNode, primaryNode; 853698a79b9SLisandro Dalcin long j, nNodes; 854698a79b9SLisandro Dalcin double affine[16]; 855698a79b9SLisandro Dalcin 856698a79b9SLisandro Dalcin if (fileFormat == 22 || !binary) { 8579566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 3, NULL, PETSC_STRING)); 8589dddd249SSatish Balay snum = sscanf(line, "%d %d %d", &correspondingDim, &correspondingTag, &primaryTag); 85908401ef6SPierre Jolivet PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 860698a79b9SLisandro Dalcin } else { 8619566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM)); 8629566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, 3)); 8639371c9d4SSatish Balay correspondingDim = ibuf[0]; 8649371c9d4SSatish Balay correspondingTag = ibuf[1]; 8659371c9d4SSatish Balay primaryTag = ibuf[2]; 866698a79b9SLisandro Dalcin } 8679371c9d4SSatish Balay (void)correspondingDim; 8689371c9d4SSatish Balay (void)correspondingTag; 8699371c9d4SSatish Balay (void)primaryTag; /* unused */ 870698a79b9SLisandro Dalcin 871698a79b9SLisandro Dalcin if (fileFormat == 22 || !binary) { 8729566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 873698a79b9SLisandro Dalcin snum = sscanf(line, "%ld", &nNodes); 8744c500f23SPierre Jolivet if (snum != 1) { /* discard transformation and try again */ 8759566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, -PETSC_MAX_PATH_LEN, NULL, PETSC_STRING)); 8769566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 877698a79b9SLisandro Dalcin snum = sscanf(line, "%ld", &nNodes); 87808401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 879698a79b9SLisandro Dalcin } 880698a79b9SLisandro Dalcin } else { 8819566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &nNodes, 1, NULL, PETSC_LONG)); 8829566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nNodes, PETSC_LONG, 1)); 8834c500f23SPierre Jolivet if (nNodes == -1) { /* discard transformation and try again */ 8849566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, affine, 16, NULL, PETSC_DOUBLE)); 8859566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &nNodes, 1, NULL, PETSC_LONG)); 8869566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nNodes, PETSC_LONG, 1)); 887698a79b9SLisandro Dalcin } 888698a79b9SLisandro Dalcin } 889698a79b9SLisandro Dalcin 890698a79b9SLisandro Dalcin for (j = 0; j < nNodes; j++) { 891698a79b9SLisandro Dalcin if (fileFormat == 22 || !binary) { 8929566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 2, NULL, PETSC_STRING)); 8939dddd249SSatish Balay snum = sscanf(line, "%d %d", &correspondingNode, &primaryNode); 89408401ef6SPierre Jolivet PetscCheck(snum == 2, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 895698a79b9SLisandro Dalcin } else { 8969566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, 2, NULL, PETSC_ENUM)); 8979566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, 2)); 8989371c9d4SSatish Balay correspondingNode = ibuf[0]; 8999371c9d4SSatish Balay primaryNode = ibuf[1]; 900698a79b9SLisandro Dalcin } 9019dddd249SSatish Balay correspondingNode = (int)nodeMap[correspondingNode]; 9029dddd249SSatish Balay primaryNode = (int)nodeMap[primaryNode]; 9039dddd249SSatish Balay periodicMap[correspondingNode] = primaryNode; 904698a79b9SLisandro Dalcin } 905698a79b9SLisandro Dalcin } 9063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 907698a79b9SLisandro Dalcin } 908698a79b9SLisandro Dalcin 9090598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 910698a79b9SLisandro Dalcin $Entities 911698a79b9SLisandro Dalcin numPoints(size_t) numCurves(size_t) 912698a79b9SLisandro Dalcin numSurfaces(size_t) numVolumes(size_t) 913698a79b9SLisandro Dalcin pointTag(int) X(double) Y(double) Z(double) 914698a79b9SLisandro Dalcin numPhysicalTags(size_t) physicalTag(int) ... 915698a79b9SLisandro Dalcin ... 916698a79b9SLisandro Dalcin curveTag(int) minX(double) minY(double) minZ(double) 917698a79b9SLisandro Dalcin maxX(double) maxY(double) maxZ(double) 918698a79b9SLisandro Dalcin numPhysicalTags(size_t) physicalTag(int) ... 919698a79b9SLisandro Dalcin numBoundingPoints(size_t) pointTag(int) ... 920698a79b9SLisandro Dalcin ... 921698a79b9SLisandro Dalcin surfaceTag(int) minX(double) minY(double) minZ(double) 922698a79b9SLisandro Dalcin maxX(double) maxY(double) maxZ(double) 923698a79b9SLisandro Dalcin numPhysicalTags(size_t) physicalTag(int) ... 924698a79b9SLisandro Dalcin numBoundingCurves(size_t) curveTag(int) ... 925698a79b9SLisandro Dalcin ... 926698a79b9SLisandro Dalcin volumeTag(int) minX(double) minY(double) minZ(double) 927698a79b9SLisandro Dalcin maxX(double) maxY(double) maxZ(double) 928698a79b9SLisandro Dalcin numPhysicalTags(size_t) physicalTag(int) ... 929698a79b9SLisandro Dalcin numBoundngSurfaces(size_t) surfaceTag(int) ... 930698a79b9SLisandro Dalcin ... 931698a79b9SLisandro Dalcin $EndEntities 932698a79b9SLisandro Dalcin */ 933d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEntities_v41(GmshFile *gmsh, GmshMesh *mesh) 934d71ae5a4SJacob Faibussowitsch { 9356497c311SBarry Smith PetscCount count[4], index, numTags; 936698a79b9SLisandro Dalcin int dim, eid, *tags = NULL; 937698a79b9SLisandro Dalcin GmshEntity *entity = NULL; 938698a79b9SLisandro Dalcin 939698a79b9SLisandro Dalcin PetscFunctionBegin; 9406497c311SBarry Smith PetscCall(GmshReadPetscCount(gmsh, count, 4)); 9419566063dSJacob Faibussowitsch PetscCall(GmshEntitiesCreate(count, &mesh->entities)); 942698a79b9SLisandro Dalcin for (dim = 0; dim < 4; ++dim) { 943698a79b9SLisandro Dalcin for (index = 0; index < count[dim]; ++index) { 9449566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, &eid, 1)); 9459566063dSJacob Faibussowitsch PetscCall(GmshEntitiesAdd(mesh->entities, (PetscInt)index, dim, eid, &entity)); 9469566063dSJacob Faibussowitsch PetscCall(GmshReadDouble(gmsh, entity->bbox, (dim == 0) ? 3 : 6)); 9476497c311SBarry Smith PetscCall(GmshReadPetscCount(gmsh, &numTags, 1)); 9489566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, numTags, sizeof(int), &tags)); 9499566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, tags, numTags)); 9506497c311SBarry Smith PetscCheck(numTags <= GMSH_MAX_TAGS, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PETSc currently supports up to %" PetscInt_FMT " tags per entity, not %" PetscCount_FMT, (PetscInt)GMSH_MAX_TAGS, numTags); 9516497c311SBarry Smith PetscCall(PetscIntCast(numTags, &entity->numTags)); 9526497c311SBarry Smith for (PetscInt i = 0; i < entity->numTags; ++i) entity->tags[i] = tags[i]; 953698a79b9SLisandro Dalcin if (dim == 0) continue; 9546497c311SBarry Smith PetscCall(GmshReadPetscCount(gmsh, &numTags, 1)); 9559566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, numTags, sizeof(int), &tags)); 9569566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, tags, numTags)); 95781a1af93SMatthew G. Knepley /* Currently, we do not save the ids for the bounding entities */ 958698a79b9SLisandro Dalcin } 959698a79b9SLisandro Dalcin } 9603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 961698a79b9SLisandro Dalcin } 962698a79b9SLisandro Dalcin 96333a088b6SMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 964698a79b9SLisandro Dalcin $Nodes 965698a79b9SLisandro Dalcin numEntityBlocks(size_t) numNodes(size_t) 966698a79b9SLisandro Dalcin minNodeTag(size_t) maxNodeTag(size_t) 967698a79b9SLisandro Dalcin entityDim(int) entityTag(int) parametric(int; 0 or 1) numNodesBlock(size_t) 968698a79b9SLisandro Dalcin nodeTag(size_t) 969698a79b9SLisandro Dalcin ... 970698a79b9SLisandro Dalcin x(double) y(double) z(double) 971698a79b9SLisandro Dalcin < u(double; if parametric and entityDim = 1 or entityDim = 2) > 972698a79b9SLisandro Dalcin < v(double; if parametric and entityDim = 2) > 973698a79b9SLisandro Dalcin ... 974698a79b9SLisandro Dalcin ... 975698a79b9SLisandro Dalcin $EndNodes 976698a79b9SLisandro Dalcin */ 977d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes_v41(GmshFile *gmsh, GmshMesh *mesh) 978d71ae5a4SJacob Faibussowitsch { 97981a1af93SMatthew G. Knepley int info[3], dim, eid, parametric; 9806497c311SBarry Smith PetscCount sizes[4], numEntityBlocks, numNodes, numNodesBlock = 0; 9816497c311SBarry Smith PetscInt numTags; 98281a1af93SMatthew G. Knepley GmshEntity *entity = NULL; 9830598e1a2SLisandro Dalcin GmshNodes *nodes; 984698a79b9SLisandro Dalcin 985698a79b9SLisandro Dalcin PetscFunctionBegin; 9866497c311SBarry Smith PetscCall(GmshReadPetscCount(gmsh, sizes, 4)); 9879371c9d4SSatish Balay numEntityBlocks = sizes[0]; 9889371c9d4SSatish Balay numNodes = sizes[1]; 9899566063dSJacob Faibussowitsch PetscCall(GmshNodesCreate(numNodes, &nodes)); 9906497c311SBarry Smith PetscCall(PetscIntCast(numNodes, &mesh->numNodes)); 9910598e1a2SLisandro Dalcin mesh->nodelist = nodes; 9926497c311SBarry Smith if (numEntityBlocks && !mesh->entities) PetscCall(PetscInfo(NULL, "File specifies %" PetscCount_FMT " entity blocks, but was missing the $Entities section\n", numEntityBlocks)); 9936497c311SBarry Smith for (PetscCount block = 0, node = 0; block < numEntityBlocks; ++block, node += numNodesBlock) { 9949566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, info, 3)); 9959371c9d4SSatish Balay dim = info[0]; 9969371c9d4SSatish Balay eid = info[1]; 9979371c9d4SSatish Balay parametric = info[2]; 998e43c9757SMatthew G. Knepley if (mesh->entities) PetscCall(GmshEntitiesGet(mesh->entities, dim, eid, &entity)); 999e43c9757SMatthew G. Knepley numTags = entity ? entity->numTags : 0; 100081a1af93SMatthew G. Knepley PetscCheck(!parametric, PETSC_COMM_SELF, PETSC_ERR_SUP, "Parametric coordinates not supported"); 10016497c311SBarry Smith PetscCall(GmshReadPetscCount(gmsh, &numNodesBlock, 1)); 10026497c311SBarry Smith PetscCall(GmshReadPetscInt(gmsh, nodes->id + node, numNodesBlock)); 10039566063dSJacob Faibussowitsch PetscCall(GmshReadDouble(gmsh, nodes->xyz + node * 3, numNodesBlock * 3)); 10046497c311SBarry Smith for (PetscCount n = 0; n < numNodesBlock; ++n) { 10057d5b9244SMatthew G. Knepley PetscInt *tags = &nodes->tag[node * GMSH_MAX_TAGS]; 10067d5b9244SMatthew G. Knepley 10076497c311SBarry Smith for (PetscInt t = 0; t < numTags; ++t) tags[n * GMSH_MAX_TAGS + t] = entity->tags[t]; 10086497c311SBarry Smith for (PetscInt t = numTags; t < GMSH_MAX_TAGS; ++t) tags[n * GMSH_MAX_TAGS + t] = -1; 10097d5b9244SMatthew G. Knepley } 1010698a79b9SLisandro Dalcin } 10116497c311SBarry Smith PetscCall(PetscIntCast(sizes[2], &gmsh->nodeStart)); 10126497c311SBarry Smith PetscCall(PetscIntCast(sizes[3] + 1, &gmsh->nodeEnd)); 10133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1014698a79b9SLisandro Dalcin } 1015698a79b9SLisandro Dalcin 101633a088b6SMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 1017698a79b9SLisandro Dalcin $Elements 1018698a79b9SLisandro Dalcin numEntityBlocks(size_t) numElements(size_t) 1019698a79b9SLisandro Dalcin minElementTag(size_t) maxElementTag(size_t) 1020698a79b9SLisandro Dalcin entityDim(int) entityTag(int) elementType(int; see below) numElementsBlock(size_t) 1021698a79b9SLisandro Dalcin elementTag(size_t) nodeTag(size_t) ... 1022698a79b9SLisandro Dalcin ... 1023698a79b9SLisandro Dalcin ... 1024698a79b9SLisandro Dalcin $EndElements 1025698a79b9SLisandro Dalcin */ 1026d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements_v41(GmshFile *gmsh, GmshMesh *mesh) 1027d71ae5a4SJacob Faibussowitsch { 10280598e1a2SLisandro Dalcin int info[3], eid, dim, cellType; 10296497c311SBarry Smith PetscCount sizes[4], numEntityBlocks, numElements, numBlockElements, numVerts, numNodes, numTags, block, elem, c, p; 1030698a79b9SLisandro Dalcin GmshEntity *entity = NULL; 1031698a79b9SLisandro Dalcin GmshElement *elements; 10326497c311SBarry Smith PetscInt *nodeMap = gmsh->nodeMap, *ibuf = NULL; 1033698a79b9SLisandro Dalcin 1034698a79b9SLisandro Dalcin PetscFunctionBegin; 10356497c311SBarry Smith PetscCall(GmshReadPetscCount(gmsh, sizes, 4)); 10369371c9d4SSatish Balay numEntityBlocks = sizes[0]; 10379371c9d4SSatish Balay numElements = sizes[1]; 10389566063dSJacob Faibussowitsch PetscCall(GmshElementsCreate(numElements, &elements)); 10396497c311SBarry Smith PetscCall(PetscIntCast(numElements, &mesh->numElems)); 10400598e1a2SLisandro Dalcin mesh->elements = elements; 10416497c311SBarry Smith if (numEntityBlocks && !mesh->entities) PetscCall(PetscInfo(NULL, "File specifies %" PetscCount_FMT " entity blocks, but was missing the $Entities section\n", numEntityBlocks)); 1042698a79b9SLisandro Dalcin for (c = 0, block = 0; block < numEntityBlocks; ++block) { 10439566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, info, 3)); 10449371c9d4SSatish Balay dim = info[0]; 10459371c9d4SSatish Balay eid = info[1]; 10469371c9d4SSatish Balay cellType = info[2]; 1047e43c9757SMatthew G. Knepley if (mesh->entities) PetscCall(GmshEntitiesGet(mesh->entities, dim, eid, &entity)); 10489566063dSJacob Faibussowitsch PetscCall(GmshCellTypeCheck(cellType)); 10490598e1a2SLisandro Dalcin numVerts = GmshCellMap[cellType].numVerts; 10500598e1a2SLisandro Dalcin numNodes = GmshCellMap[cellType].numNodes; 1051e43c9757SMatthew G. Knepley numTags = entity ? entity->numTags : 0; 10526497c311SBarry Smith PetscCall(GmshReadPetscCount(gmsh, &numBlockElements, 1)); 10539566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, (1 + numNodes) * numBlockElements, sizeof(PetscInt), &ibuf)); 10546497c311SBarry Smith PetscCall(GmshReadPetscInt(gmsh, ibuf, (1 + numNodes) * numBlockElements)); 1055698a79b9SLisandro Dalcin for (elem = 0; elem < numBlockElements; ++elem, ++c) { 1056698a79b9SLisandro Dalcin GmshElement *element = elements + c; 10570598e1a2SLisandro Dalcin const PetscInt *id = ibuf + elem * (1 + numNodes), *nodes = id + 1; 10586497c311SBarry Smith 1059698a79b9SLisandro Dalcin element->id = id[0]; 1060698a79b9SLisandro Dalcin element->dim = dim; 1061698a79b9SLisandro Dalcin element->cellType = cellType; 10626497c311SBarry Smith PetscCall(PetscIntCast(numVerts, &element->numVerts)); 10636497c311SBarry Smith PetscCall(PetscIntCast(numNodes, &element->numNodes)); 10646497c311SBarry Smith PetscCall(PetscIntCast(numTags, &element->numTags)); 10656497c311SBarry Smith PetscCall(PetscSegBufferGet(mesh->segbuf, element->numNodes, &element->nodes)); 10660598e1a2SLisandro Dalcin for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]]; 10670598e1a2SLisandro Dalcin for (p = 0; p < element->numTags; p++) element->tags[p] = entity->tags[p]; 1068698a79b9SLisandro Dalcin } 1069698a79b9SLisandro Dalcin } 10703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1071698a79b9SLisandro Dalcin } 1072698a79b9SLisandro Dalcin 10730598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 1074698a79b9SLisandro Dalcin $Periodic 1075698a79b9SLisandro Dalcin numPeriodicLinks(size_t) 10769dddd249SSatish Balay entityDim(int) entityTag(int) entityTagPrimary(int) 1077698a79b9SLisandro Dalcin numAffine(size_t) value(double) ... 1078698a79b9SLisandro Dalcin numCorrespondingNodes(size_t) 10799dddd249SSatish Balay nodeTag(size_t) nodeTagPrimary(size_t) 1080698a79b9SLisandro Dalcin ... 1081698a79b9SLisandro Dalcin ... 1082698a79b9SLisandro Dalcin $EndPeriodic 1083698a79b9SLisandro Dalcin */ 1084d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPeriodic_v41(GmshFile *gmsh, PetscInt periodicMap[]) 1085d71ae5a4SJacob Faibussowitsch { 1086698a79b9SLisandro Dalcin int info[3]; 1087698a79b9SLisandro Dalcin double dbuf[16]; 10886497c311SBarry Smith PetscCount numPeriodicLinks, numAffine, numCorrespondingNodes; 10896497c311SBarry Smith PetscInt *nodeMap = gmsh->nodeMap, *nodeTags = NULL; 1090698a79b9SLisandro Dalcin 1091698a79b9SLisandro Dalcin PetscFunctionBegin; 10926497c311SBarry Smith PetscCall(GmshReadPetscCount(gmsh, &numPeriodicLinks, 1)); 10936497c311SBarry Smith for (PetscCount link = 0; link < numPeriodicLinks; ++link) { 10949566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, info, 3)); 10956497c311SBarry Smith PetscCall(GmshReadPetscCount(gmsh, &numAffine, 1)); 10969566063dSJacob Faibussowitsch PetscCall(GmshReadDouble(gmsh, dbuf, numAffine)); 10976497c311SBarry Smith PetscCall(GmshReadPetscCount(gmsh, &numCorrespondingNodes, 1)); 10989566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, numCorrespondingNodes, sizeof(PetscInt), &nodeTags)); 10996497c311SBarry Smith PetscCall(GmshReadPetscInt(gmsh, nodeTags, numCorrespondingNodes * 2)); 11006497c311SBarry Smith for (PetscCount node = 0; node < numCorrespondingNodes; ++node) { 11019dddd249SSatish Balay PetscInt correspondingNode = nodeMap[nodeTags[node * 2 + 0]]; 11029dddd249SSatish Balay PetscInt primaryNode = nodeMap[nodeTags[node * 2 + 1]]; 11036497c311SBarry Smith 11049dddd249SSatish Balay periodicMap[correspondingNode] = primaryNode; 1105698a79b9SLisandro Dalcin } 1106698a79b9SLisandro Dalcin } 11073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1108698a79b9SLisandro Dalcin } 1109698a79b9SLisandro Dalcin 11100598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 1111d6689ca9SLisandro Dalcin $MeshFormat // same as MSH version 2 1112d6689ca9SLisandro Dalcin version(ASCII double; currently 4.1) 1113d6689ca9SLisandro Dalcin file-type(ASCII int; 0 for ASCII mode, 1 for binary mode) 1114d6689ca9SLisandro Dalcin data-size(ASCII int; sizeof(size_t)) 1115d6689ca9SLisandro Dalcin < int with value one; only in binary mode, to detect endianness > 1116d6689ca9SLisandro Dalcin $EndMeshFormat 1117d6689ca9SLisandro Dalcin */ 1118d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadMeshFormat(GmshFile *gmsh) 1119d71ae5a4SJacob Faibussowitsch { 1120698a79b9SLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 1121698a79b9SLisandro Dalcin int snum, fileType, fileFormat, dataSize, checkEndian; 1122698a79b9SLisandro Dalcin float version; 1123698a79b9SLisandro Dalcin 1124698a79b9SLisandro Dalcin PetscFunctionBegin; 11259566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 3)); 1126698a79b9SLisandro Dalcin snum = sscanf(line, "%f %d %d", &version, &fileType, &dataSize); 1127a8d4e440SJunchao Zhang fileFormat = (int)roundf(version * 10); 112808401ef6SPierre Jolivet PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line); 1129a8d4e440SJunchao Zhang PetscCheck(fileFormat >= 22, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at least 2.2", (double)version); 11301dca8a05SBarry Smith PetscCheck((int)version != 3, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f not supported", (double)version); 1131a8d4e440SJunchao Zhang PetscCheck(fileFormat <= 41, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at most 4.1", (double)version); 113208401ef6SPierre Jolivet PetscCheck(!gmsh->binary || fileType, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Viewer is binary but Gmsh file is ASCII"); 113308401ef6SPierre Jolivet PetscCheck(gmsh->binary || !fileType, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Viewer is ASCII but Gmsh file is binary"); 11341dca8a05SBarry 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); 11351dca8a05SBarry 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); 1136698a79b9SLisandro Dalcin gmsh->fileFormat = fileFormat; 1137698a79b9SLisandro Dalcin gmsh->dataSize = dataSize; 1138698a79b9SLisandro Dalcin gmsh->byteSwap = PETSC_FALSE; 1139698a79b9SLisandro Dalcin if (gmsh->binary) { 11409566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, &checkEndian, 1)); 1141698a79b9SLisandro Dalcin if (checkEndian != 1) { 11429566063dSJacob Faibussowitsch PetscCall(PetscByteSwap(&checkEndian, PETSC_ENUM, 1)); 114308401ef6SPierre Jolivet PetscCheck(checkEndian == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to detect endianness in Gmsh file header: %s", line); 1144698a79b9SLisandro Dalcin gmsh->byteSwap = PETSC_TRUE; 1145698a79b9SLisandro Dalcin } 1146698a79b9SLisandro Dalcin } 11473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1148698a79b9SLisandro Dalcin } 1149698a79b9SLisandro Dalcin 11508749820aSMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 11518749820aSMatthew G. Knepley Neper: https://neper.info/ adds this section 11528749820aSMatthew G. Knepley 11538749820aSMatthew G. Knepley $MeshVersion 11548749820aSMatthew G. Knepley <major>.<minor>,<patch> 11558749820aSMatthew G. Knepley $EndMeshVersion 11568749820aSMatthew G. Knepley */ 11578749820aSMatthew G. Knepley static PetscErrorCode GmshReadMeshVersion(GmshFile *gmsh) 11588749820aSMatthew G. Knepley { 11598749820aSMatthew G. Knepley char line[PETSC_MAX_PATH_LEN]; 11608749820aSMatthew G. Knepley int snum, major, minor, patch; 11618749820aSMatthew G. Knepley 11628749820aSMatthew G. Knepley PetscFunctionBegin; 11638749820aSMatthew G. Knepley PetscCall(GmshReadString(gmsh, line, 1)); 11648749820aSMatthew G. Knepley snum = sscanf(line, "%d.%d.%d", &major, &minor, &patch); 11658749820aSMatthew G. Knepley PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line); 11668749820aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 11678749820aSMatthew G. Knepley } 11688749820aSMatthew G. Knepley 11698749820aSMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 11708749820aSMatthew G. Knepley Neper: https://neper.info/ adds this section 11718749820aSMatthew G. Knepley 11728749820aSMatthew G. Knepley $Domain 11738749820aSMatthew G. Knepley <shape> 11748749820aSMatthew G. Knepley $EndDomain 11758749820aSMatthew G. Knepley */ 11768749820aSMatthew G. Knepley static PetscErrorCode GmshReadMeshDomain(GmshFile *gmsh) 11778749820aSMatthew G. Knepley { 11788749820aSMatthew G. Knepley char line[PETSC_MAX_PATH_LEN]; 11798749820aSMatthew G. Knepley 11808749820aSMatthew G. Knepley PetscFunctionBegin; 11818749820aSMatthew G. Knepley PetscCall(GmshReadString(gmsh, line, 1)); 11828749820aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 11838749820aSMatthew G. Knepley } 11848749820aSMatthew G. Knepley 11851f643af3SLisandro Dalcin /* 11861f643af3SLisandro Dalcin PhysicalNames 11871f643af3SLisandro Dalcin numPhysicalNames(ASCII int) 11881f643af3SLisandro Dalcin dimension(ASCII int) physicalTag(ASCII int) "name"(127 characters max) 11891f643af3SLisandro Dalcin ... 11901f643af3SLisandro Dalcin $EndPhysicalNames 11911f643af3SLisandro Dalcin */ 1192d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPhysicalNames(GmshFile *gmsh, GmshMesh *mesh) 1193d71ae5a4SJacob Faibussowitsch { 1194bbcf679cSJacob Faibussowitsch char line[PETSC_MAX_PATH_LEN], name[128 + 2], *p = NULL, *q = NULL, *r = NULL; 1195a45dabc8SMatthew G. Knepley int snum, region, dim, tag; 1196698a79b9SLisandro Dalcin 1197698a79b9SLisandro Dalcin PetscFunctionBegin; 11989566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 1)); 1199a45dabc8SMatthew G. Knepley snum = sscanf(line, "%d", ®ion); 1200a45dabc8SMatthew G. Knepley mesh->numRegions = region; 120108401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 120290d778b8SLisandro Dalcin PetscCall(PetscMalloc3(mesh->numRegions, &mesh->regionDims, mesh->numRegions, &mesh->regionTags, mesh->numRegions, &mesh->regionNames)); 1203a45dabc8SMatthew G. Knepley for (region = 0; region < mesh->numRegions; ++region) { 12049566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 2)); 12051f643af3SLisandro Dalcin snum = sscanf(line, "%d %d", &dim, &tag); 120608401ef6SPierre Jolivet PetscCheck(snum == 2, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 12079566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, -(PetscInt)sizeof(line))); 12089566063dSJacob Faibussowitsch PetscCall(PetscStrchr(line, '"', &p)); 120928b400f6SJacob Faibussowitsch PetscCheck(p, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 12109566063dSJacob Faibussowitsch PetscCall(PetscStrrchr(line, '"', &q)); 121108401ef6SPierre Jolivet PetscCheck(q != p, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 12125f5cd6d5SMatthew G. Knepley PetscCall(PetscStrrchr(line, ':', &r)); 12135f5cd6d5SMatthew G. Knepley if (p != r) q = r; 12149566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(name, p + 1, (size_t)(q - p - 1))); 121590d778b8SLisandro Dalcin mesh->regionDims[region] = dim; 1216a45dabc8SMatthew G. Knepley mesh->regionTags[region] = tag; 12179566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(name, &mesh->regionNames[region])); 1218698a79b9SLisandro Dalcin } 12193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1220de78e4feSLisandro Dalcin } 1221de78e4feSLisandro Dalcin 1222d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEntities(GmshFile *gmsh, GmshMesh *mesh) 1223d71ae5a4SJacob Faibussowitsch { 12240598e1a2SLisandro Dalcin PetscFunctionBegin; 12250598e1a2SLisandro Dalcin switch (gmsh->fileFormat) { 1226d71ae5a4SJacob Faibussowitsch case 41: 1227d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadEntities_v41(gmsh, mesh)); 1228d71ae5a4SJacob Faibussowitsch break; 1229d71ae5a4SJacob Faibussowitsch default: 1230d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadEntities_v40(gmsh, mesh)); 1231d71ae5a4SJacob Faibussowitsch break; 123296ca5757SLisandro Dalcin } 12333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12340598e1a2SLisandro Dalcin } 12350598e1a2SLisandro Dalcin 1236d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes(GmshFile *gmsh, GmshMesh *mesh) 1237d71ae5a4SJacob Faibussowitsch { 12380598e1a2SLisandro Dalcin PetscFunctionBegin; 12390598e1a2SLisandro Dalcin switch (gmsh->fileFormat) { 1240d71ae5a4SJacob Faibussowitsch case 41: 1241d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadNodes_v41(gmsh, mesh)); 1242d71ae5a4SJacob Faibussowitsch break; 1243d71ae5a4SJacob Faibussowitsch case 40: 1244d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadNodes_v40(gmsh, mesh)); 1245d71ae5a4SJacob Faibussowitsch break; 1246d71ae5a4SJacob Faibussowitsch default: 1247d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadNodes_v22(gmsh, mesh)); 1248d71ae5a4SJacob Faibussowitsch break; 12490598e1a2SLisandro Dalcin } 12500598e1a2SLisandro Dalcin 12510598e1a2SLisandro Dalcin { /* Gmsh v2.2/v4.0 does not provide min/max node tags */ 12520598e1a2SLisandro Dalcin if (mesh->numNodes > 0 && gmsh->nodeEnd >= gmsh->nodeStart) { 1253*1690c2aeSBarry Smith PetscInt tagMin = PETSC_INT_MAX, tagMax = PETSC_INT_MIN, n; 12540598e1a2SLisandro Dalcin GmshNodes *nodes = mesh->nodelist; 12550598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) { 12560598e1a2SLisandro Dalcin const PetscInt tag = nodes->id[n]; 12570598e1a2SLisandro Dalcin tagMin = PetscMin(tag, tagMin); 12580598e1a2SLisandro Dalcin tagMax = PetscMax(tag, tagMax); 12590598e1a2SLisandro Dalcin } 12600598e1a2SLisandro Dalcin gmsh->nodeStart = tagMin; 12610598e1a2SLisandro Dalcin gmsh->nodeEnd = tagMax + 1; 12620598e1a2SLisandro Dalcin } 12630598e1a2SLisandro Dalcin } 12640598e1a2SLisandro Dalcin 12650598e1a2SLisandro Dalcin { /* Support for sparse node tags */ 12660598e1a2SLisandro Dalcin PetscInt n, t; 12670598e1a2SLisandro Dalcin GmshNodes *nodes = mesh->nodelist; 12689566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(gmsh->nodeEnd - gmsh->nodeStart, &gmsh->nbuf)); 1269*1690c2aeSBarry Smith for (t = 0; t < gmsh->nodeEnd - gmsh->nodeStart; ++t) gmsh->nbuf[t] = PETSC_INT_MIN; 12700598e1a2SLisandro Dalcin gmsh->nodeMap = gmsh->nbuf - gmsh->nodeStart; 12710598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) { 12720598e1a2SLisandro Dalcin const PetscInt tag = nodes->id[n]; 127363a3b9bcSJacob Faibussowitsch PetscCheck(gmsh->nodeMap[tag] < 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Repeated node tag %" PetscInt_FMT, tag); 12740598e1a2SLisandro Dalcin gmsh->nodeMap[tag] = n; 12750598e1a2SLisandro Dalcin } 12760598e1a2SLisandro Dalcin } 12773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12780598e1a2SLisandro Dalcin } 12790598e1a2SLisandro Dalcin 1280d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements(GmshFile *gmsh, GmshMesh *mesh) 1281d71ae5a4SJacob Faibussowitsch { 12820598e1a2SLisandro Dalcin PetscFunctionBegin; 12830598e1a2SLisandro Dalcin switch (gmsh->fileFormat) { 1284d71ae5a4SJacob Faibussowitsch case 41: 1285d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadElements_v41(gmsh, mesh)); 1286d71ae5a4SJacob Faibussowitsch break; 1287d71ae5a4SJacob Faibussowitsch case 40: 1288d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadElements_v40(gmsh, mesh)); 1289d71ae5a4SJacob Faibussowitsch break; 1290d71ae5a4SJacob Faibussowitsch default: 1291d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadElements_v22(gmsh, mesh)); 1292d71ae5a4SJacob Faibussowitsch break; 12930598e1a2SLisandro Dalcin } 12940598e1a2SLisandro Dalcin 12950598e1a2SLisandro Dalcin { /* Reorder elements by codimension and polytope type */ 12960598e1a2SLisandro Dalcin PetscInt ne = mesh->numElems; 12970598e1a2SLisandro Dalcin GmshElement *elements = mesh->elements; 1298066ea43fSLisandro Dalcin PetscInt keymap[GMSH_NUM_POLYTOPES], nk = 0; 1299066ea43fSLisandro Dalcin PetscInt offset[GMSH_NUM_POLYTOPES + 1], e, k; 13000598e1a2SLisandro Dalcin 1301*1690c2aeSBarry Smith for (k = 0; k < GMSH_NUM_POLYTOPES; ++k) keymap[k] = PETSC_INT_MIN; 13029566063dSJacob Faibussowitsch PetscCall(PetscMemzero(offset, sizeof(offset))); 13030598e1a2SLisandro Dalcin 1304066ea43fSLisandro Dalcin keymap[GMSH_TET] = nk++; 1305066ea43fSLisandro Dalcin keymap[GMSH_HEX] = nk++; 1306066ea43fSLisandro Dalcin keymap[GMSH_PRI] = nk++; 1307066ea43fSLisandro Dalcin keymap[GMSH_PYR] = nk++; 1308066ea43fSLisandro Dalcin keymap[GMSH_TRI] = nk++; 1309066ea43fSLisandro Dalcin keymap[GMSH_QUA] = nk++; 1310066ea43fSLisandro Dalcin keymap[GMSH_SEG] = nk++; 1311066ea43fSLisandro Dalcin keymap[GMSH_VTX] = nk++; 13120598e1a2SLisandro Dalcin 13139566063dSJacob Faibussowitsch PetscCall(GmshElementsCreate(mesh->numElems, &mesh->elements)); 13144ad8454bSPierre Jolivet #define key(eid) keymap[GmshCellMap[elements[eid].cellType].polytope] 13150598e1a2SLisandro Dalcin for (e = 0; e < ne; ++e) offset[1 + key(e)]++; 13160598e1a2SLisandro Dalcin for (k = 1; k < nk; ++k) offset[k] += offset[k - 1]; 13170598e1a2SLisandro Dalcin for (e = 0; e < ne; ++e) mesh->elements[offset[key(e)]++] = elements[e]; 13180598e1a2SLisandro Dalcin #undef key 13199566063dSJacob Faibussowitsch PetscCall(GmshElementsDestroy(&elements)); 1320066ea43fSLisandro Dalcin } 13210598e1a2SLisandro Dalcin 1322066ea43fSLisandro Dalcin { /* Mesh dimension and order */ 1323066ea43fSLisandro Dalcin GmshElement *elem = mesh->numElems ? mesh->elements : NULL; 1324066ea43fSLisandro Dalcin mesh->dim = elem ? GmshCellMap[elem->cellType].dim : 0; 1325066ea43fSLisandro Dalcin mesh->order = elem ? GmshCellMap[elem->cellType].order : 0; 13260598e1a2SLisandro Dalcin } 13270598e1a2SLisandro Dalcin 13280598e1a2SLisandro Dalcin { 13290598e1a2SLisandro Dalcin PetscBT vtx; 13300598e1a2SLisandro Dalcin PetscInt dim = mesh->dim, e, n, v; 13310598e1a2SLisandro Dalcin 13329566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(mesh->numNodes, &vtx)); 13330598e1a2SLisandro Dalcin 13340598e1a2SLisandro Dalcin /* Compute number of cells and set of vertices */ 13350598e1a2SLisandro Dalcin mesh->numCells = 0; 13360598e1a2SLisandro Dalcin for (e = 0; e < mesh->numElems; ++e) { 13370598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + e; 13380598e1a2SLisandro Dalcin if (elem->dim == dim && dim > 0) mesh->numCells++; 133948a46eb9SPierre Jolivet for (v = 0; v < elem->numVerts; v++) PetscCall(PetscBTSet(vtx, elem->nodes[v])); 13400598e1a2SLisandro Dalcin } 13410598e1a2SLisandro Dalcin 13420598e1a2SLisandro Dalcin /* Compute numbering for vertices */ 13430598e1a2SLisandro Dalcin mesh->numVerts = 0; 13449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mesh->numNodes, &mesh->vertexMap)); 1345*1690c2aeSBarry Smith for (n = 0; n < mesh->numNodes; ++n) mesh->vertexMap[n] = PetscBTLookup(vtx, n) ? mesh->numVerts++ : PETSC_INT_MIN; 13460598e1a2SLisandro Dalcin 13479566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&vtx)); 13480598e1a2SLisandro Dalcin } 13493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13500598e1a2SLisandro Dalcin } 13510598e1a2SLisandro Dalcin 1352d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPeriodic(GmshFile *gmsh, GmshMesh *mesh) 1353d71ae5a4SJacob Faibussowitsch { 13540598e1a2SLisandro Dalcin PetscInt n; 13550598e1a2SLisandro Dalcin 13560598e1a2SLisandro Dalcin PetscFunctionBegin; 13579566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mesh->numNodes, &mesh->periodMap)); 13580598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) mesh->periodMap[n] = n; 13590598e1a2SLisandro Dalcin switch (gmsh->fileFormat) { 1360d71ae5a4SJacob Faibussowitsch case 41: 1361d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadPeriodic_v41(gmsh, mesh->periodMap)); 1362d71ae5a4SJacob Faibussowitsch break; 1363d71ae5a4SJacob Faibussowitsch default: 1364d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadPeriodic_v40(gmsh, mesh->periodMap)); 1365d71ae5a4SJacob Faibussowitsch break; 13660598e1a2SLisandro Dalcin } 13670598e1a2SLisandro Dalcin 13689dddd249SSatish Balay /* Find canonical primary nodes */ 13690598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) 13709371c9d4SSatish Balay while (mesh->periodMap[n] != mesh->periodMap[mesh->periodMap[n]]) mesh->periodMap[n] = mesh->periodMap[mesh->periodMap[n]]; 13710598e1a2SLisandro Dalcin 13729dddd249SSatish Balay /* Renumber vertices (filter out correspondings) */ 13730598e1a2SLisandro Dalcin mesh->numVerts = 0; 13740598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) 13750598e1a2SLisandro Dalcin if (mesh->vertexMap[n] >= 0) /* is vertex */ 13769dddd249SSatish Balay if (mesh->periodMap[n] == n) /* is primary */ 13770598e1a2SLisandro Dalcin mesh->vertexMap[n] = mesh->numVerts++; 13780598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) 13790598e1a2SLisandro Dalcin if (mesh->vertexMap[n] >= 0) /* is vertex */ 13809dddd249SSatish Balay if (mesh->periodMap[n] != n) /* is corresponding */ 13810598e1a2SLisandro Dalcin mesh->vertexMap[n] = mesh->vertexMap[mesh->periodMap[n]]; 13823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13830598e1a2SLisandro Dalcin } 13840598e1a2SLisandro Dalcin 1385066ea43fSLisandro Dalcin #define DM_POLYTOPE_VERTEX DM_POLYTOPE_POINT 1386066ea43fSLisandro Dalcin static const DMPolytopeType DMPolytopeMap[] = { 1387066ea43fSLisandro Dalcin /* GMSH_VTX */ DM_POLYTOPE_VERTEX, 1388066ea43fSLisandro Dalcin /* GMSH_SEG */ DM_POLYTOPE_SEGMENT, 1389066ea43fSLisandro Dalcin /* GMSH_TRI */ DM_POLYTOPE_TRIANGLE, 1390066ea43fSLisandro Dalcin /* GMSH_QUA */ DM_POLYTOPE_QUADRILATERAL, 1391066ea43fSLisandro Dalcin /* GMSH_TET */ DM_POLYTOPE_TETRAHEDRON, 1392066ea43fSLisandro Dalcin /* GMSH_HEX */ DM_POLYTOPE_HEXAHEDRON, 1393066ea43fSLisandro Dalcin /* GMSH_PRI */ DM_POLYTOPE_TRI_PRISM, 13949371c9d4SSatish Balay /* GMSH_PYR */ DM_POLYTOPE_PYRAMID, DM_POLYTOPE_UNKNOWN}; 13950598e1a2SLisandro Dalcin 1396d71ae5a4SJacob Faibussowitsch static inline DMPolytopeType DMPolytopeTypeFromGmsh(PetscInt cellType) 1397d71ae5a4SJacob Faibussowitsch { 1398066ea43fSLisandro Dalcin return DMPolytopeMap[GmshCellMap[cellType].polytope]; 1399066ea43fSLisandro Dalcin } 1400066ea43fSLisandro Dalcin 1401d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshCreateFE(MPI_Comm comm, const char prefix[], PetscBool isSimplex, PetscBool continuity, PetscDTNodeType nodeType, PetscInt dim, PetscInt Nc, PetscInt k, PetscFE *fem) 1402d71ae5a4SJacob Faibussowitsch { 1403066ea43fSLisandro Dalcin DM K; 1404066ea43fSLisandro Dalcin PetscSpace P; 1405066ea43fSLisandro Dalcin PetscDualSpace Q; 1406066ea43fSLisandro Dalcin PetscQuadrature q, fq; 1407066ea43fSLisandro Dalcin PetscBool isTensor = isSimplex ? PETSC_FALSE : PETSC_TRUE; 1408066ea43fSLisandro Dalcin PetscBool endpoint = PETSC_TRUE; 1409066ea43fSLisandro Dalcin char name[32]; 1410066ea43fSLisandro Dalcin 1411066ea43fSLisandro Dalcin PetscFunctionBegin; 1412066ea43fSLisandro Dalcin /* Create space */ 14139566063dSJacob Faibussowitsch PetscCall(PetscSpaceCreate(comm, &P)); 14149566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetType(P, PETSCSPACEPOLYNOMIAL)); 14159566063dSJacob Faibussowitsch PetscCall(PetscSpacePolynomialSetTensor(P, isTensor)); 14169566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumComponents(P, Nc)); 14179566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumVariables(P, dim)); 14189566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetDegree(P, k, PETSC_DETERMINE)); 1419066ea43fSLisandro Dalcin if (prefix) { 14209566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)P, prefix)); 14219566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetFromOptions(P)); 14229566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)P, NULL)); 14239566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetDegree(P, &k, NULL)); 1424066ea43fSLisandro Dalcin } 14259566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetUp(P)); 1426066ea43fSLisandro Dalcin /* Create dual space */ 14279566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceCreate(comm, &Q)); 14289566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetType(Q, PETSCDUALSPACELAGRANGE)); 14299566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceLagrangeSetTensor(Q, isTensor)); 14309566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceLagrangeSetContinuity(Q, continuity)); 14319566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceLagrangeSetNodeType(Q, nodeType, endpoint, 0)); 14329566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetNumComponents(Q, Nc)); 14339566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetOrder(Q, k)); 14349566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell(PETSC_COMM_SELF, DMPolytopeTypeSimpleShape(dim, isSimplex), &K)); 14359566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetDM(Q, K)); 14369566063dSJacob Faibussowitsch PetscCall(DMDestroy(&K)); 1437066ea43fSLisandro Dalcin if (prefix) { 14389566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)Q, prefix)); 14399566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetFromOptions(Q)); 14409566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)Q, NULL)); 1441066ea43fSLisandro Dalcin } 14429566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetUp(Q)); 1443066ea43fSLisandro Dalcin /* Create quadrature */ 1444066ea43fSLisandro Dalcin if (isSimplex) { 14459566063dSJacob Faibussowitsch PetscCall(PetscDTStroudConicalQuadrature(dim, 1, k + 1, -1, +1, &q)); 14469566063dSJacob Faibussowitsch PetscCall(PetscDTStroudConicalQuadrature(dim - 1, 1, k + 1, -1, +1, &fq)); 1447066ea43fSLisandro Dalcin } else { 14489566063dSJacob Faibussowitsch PetscCall(PetscDTGaussTensorQuadrature(dim, 1, k + 1, -1, +1, &q)); 14499566063dSJacob Faibussowitsch PetscCall(PetscDTGaussTensorQuadrature(dim - 1, 1, k + 1, -1, +1, &fq)); 1450066ea43fSLisandro Dalcin } 1451066ea43fSLisandro Dalcin /* Create finite element */ 14529566063dSJacob Faibussowitsch PetscCall(PetscFECreate(comm, fem)); 14539566063dSJacob Faibussowitsch PetscCall(PetscFESetType(*fem, PETSCFEBASIC)); 14549566063dSJacob Faibussowitsch PetscCall(PetscFESetNumComponents(*fem, Nc)); 14559566063dSJacob Faibussowitsch PetscCall(PetscFESetBasisSpace(*fem, P)); 14569566063dSJacob Faibussowitsch PetscCall(PetscFESetDualSpace(*fem, Q)); 14579566063dSJacob Faibussowitsch PetscCall(PetscFESetQuadrature(*fem, q)); 14589566063dSJacob Faibussowitsch PetscCall(PetscFESetFaceQuadrature(*fem, fq)); 1459066ea43fSLisandro Dalcin if (prefix) { 14609566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*fem, prefix)); 14619566063dSJacob Faibussowitsch PetscCall(PetscFESetFromOptions(*fem)); 14629566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*fem, NULL)); 1463066ea43fSLisandro Dalcin } 14649566063dSJacob Faibussowitsch PetscCall(PetscFESetUp(*fem)); 1465066ea43fSLisandro Dalcin /* Cleanup */ 14669566063dSJacob Faibussowitsch PetscCall(PetscSpaceDestroy(&P)); 14679566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceDestroy(&Q)); 14689566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&q)); 14699566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&fq)); 1470066ea43fSLisandro Dalcin /* Set finite element name */ 147163a3b9bcSJacob Faibussowitsch PetscCall(PetscSNPrintf(name, sizeof(name), "%s%" PetscInt_FMT, isSimplex ? "P" : "Q", k)); 14729566063dSJacob Faibussowitsch PetscCall(PetscFESetName(*fem, name)); 14733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 147496ca5757SLisandro Dalcin } 147596ca5757SLisandro Dalcin 1476cc4c1da9SBarry Smith /*@ 1477a1cb98faSBarry Smith DMPlexCreateGmshFromFile - Create a `DMPLEX` mesh from a Gmsh file 1478d6689ca9SLisandro Dalcin 1479a4e35b19SJacob Faibussowitsch Input Parameters: 1480d6689ca9SLisandro Dalcin + comm - The MPI communicator 1481d6689ca9SLisandro Dalcin . filename - Name of the Gmsh file 1482d6689ca9SLisandro Dalcin - interpolate - Create faces and edges in the mesh 1483d6689ca9SLisandro Dalcin 1484d6689ca9SLisandro Dalcin Output Parameter: 1485a1cb98faSBarry Smith . dm - The `DM` object representing the mesh 1486d6689ca9SLisandro Dalcin 1487d6689ca9SLisandro Dalcin Level: beginner 1488d6689ca9SLisandro Dalcin 14891cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()` 1490d6689ca9SLisandro Dalcin @*/ 1491d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateGmshFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) 1492d71ae5a4SJacob Faibussowitsch { 1493d6689ca9SLisandro Dalcin PetscViewer viewer; 1494d6689ca9SLisandro Dalcin PetscMPIInt rank; 1495d6689ca9SLisandro Dalcin int fileType; 1496d6689ca9SLisandro Dalcin PetscViewerType vtype; 1497d6689ca9SLisandro Dalcin 1498d6689ca9SLisandro Dalcin PetscFunctionBegin; 14999566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1500d6689ca9SLisandro Dalcin 1501d6689ca9SLisandro Dalcin /* Determine Gmsh file type (ASCII or binary) from file header */ 1502dd400576SPatrick Sanan if (rank == 0) { 15030598e1a2SLisandro Dalcin GmshFile gmsh[1]; 1504d6689ca9SLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 1505d6689ca9SLisandro Dalcin int snum; 1506d6689ca9SLisandro Dalcin float version; 1507a8d4e440SJunchao Zhang int fileFormat; 1508d6689ca9SLisandro Dalcin 15099566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(gmsh, 1)); 15109566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(PETSC_COMM_SELF, &gmsh->viewer)); 15119566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(gmsh->viewer, PETSCVIEWERASCII)); 15129566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(gmsh->viewer, FILE_MODE_READ)); 15139566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(gmsh->viewer, filename)); 1514d6689ca9SLisandro Dalcin /* Read only the first two lines of the Gmsh file */ 15159566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 15169566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$MeshFormat", line)); 15179566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 2)); 1518d6689ca9SLisandro Dalcin snum = sscanf(line, "%f %d", &version, &fileType); 1519a8d4e440SJunchao Zhang fileFormat = (int)roundf(version * 10); 152008401ef6SPierre Jolivet PetscCheck(snum == 2, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line); 1521a8d4e440SJunchao Zhang PetscCheck(fileFormat >= 22, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at least 2.2", (double)version); 15221dca8a05SBarry Smith PetscCheck((int)version != 3, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f not supported", (double)version); 1523a8d4e440SJunchao Zhang PetscCheck(fileFormat <= 41, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at most 4.1", (double)version); 15249566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&gmsh->viewer)); 1525d6689ca9SLisandro Dalcin } 15269566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&fileType, 1, MPI_INT, 0, comm)); 1527d6689ca9SLisandro Dalcin vtype = (fileType == 0) ? PETSCVIEWERASCII : PETSCVIEWERBINARY; 1528d6689ca9SLisandro Dalcin 1529d6689ca9SLisandro Dalcin /* Create appropriate viewer and build plex */ 15309566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 15319566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, vtype)); 15329566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 15339566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 15349566063dSJacob Faibussowitsch PetscCall(DMPlexCreateGmsh(comm, viewer, interpolate, dm)); 15359566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 15363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1537d6689ca9SLisandro Dalcin } 1538d6689ca9SLisandro Dalcin 1539331830f3SMatthew G. Knepley /*@ 1540a1cb98faSBarry Smith DMPlexCreateGmsh - Create a `DMPLEX` mesh from a Gmsh file viewer 1541331830f3SMatthew G. Knepley 1542d083f849SBarry Smith Collective 1543331830f3SMatthew G. Knepley 1544331830f3SMatthew G. Knepley Input Parameters: 1545331830f3SMatthew G. Knepley + comm - The MPI communicator 1546a1cb98faSBarry Smith . viewer - The `PetscViewer` associated with a Gmsh file 1547331830f3SMatthew G. Knepley - interpolate - Create faces and edges in the mesh 1548331830f3SMatthew G. Knepley 1549331830f3SMatthew G. Knepley Output Parameter: 1550a1cb98faSBarry Smith . dm - The `DM` object representing the mesh 1551331830f3SMatthew G. Knepley 1552a1cb98faSBarry Smith Options Database Keys: 1553df93260fSMatthew G. Knepley + -dm_plex_gmsh_hybrid - Force triangular prisms to use tensor order 1554df93260fSMatthew G. Knepley . -dm_plex_gmsh_periodic - Read Gmsh periodic section and construct a periodic Plex 1555df93260fSMatthew G. Knepley . -dm_plex_gmsh_highorder - Generate high-order coordinates 1556df93260fSMatthew 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 15572b205333SMatthew G. Knepley . -dm_plex_gmsh_use_generic - Generate generic labels, i.e. Cell Sets, Face Sets, etc. 1558df93260fSMatthew G. Knepley . -dm_plex_gmsh_use_regions - Generate labels with region names 1559df93260fSMatthew G. Knepley . -dm_plex_gmsh_mark_vertices - Add vertices to generated labels 1560df93260fSMatthew G. Knepley . -dm_plex_gmsh_multiple_tags - Allow multiple tags for default labels 1561df93260fSMatthew G. Knepley - -dm_plex_gmsh_spacedim <d> - Embedding space dimension, if different from topological dimension 1562df93260fSMatthew G. Knepley 15631d27aa22SBarry Smith Level: beginner 15641d27aa22SBarry Smith 15651d27aa22SBarry Smith Notes: 15661d27aa22SBarry Smith The Gmsh file format is described in <http://gmsh.info/doc/texinfo/gmsh.html#MSH-file-format> 1567df93260fSMatthew G. Knepley 15686497c311SBarry Smith 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`. 1569331830f3SMatthew G. Knepley 15701cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()` 1571331830f3SMatthew G. Knepley @*/ 1572d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateGmsh(MPI_Comm comm, PetscViewer viewer, PetscBool interpolate, DM *dm) 1573d71ae5a4SJacob Faibussowitsch { 15740598e1a2SLisandro Dalcin GmshMesh *mesh = NULL; 157511c56cb0SLisandro Dalcin PetscViewer parentviewer = NULL; 15760598e1a2SLisandro Dalcin PetscBT periodicVerts = NULL; 1577eae3dc7dSJacob Faibussowitsch PetscBT *periodicCells = NULL; 15786858538eSMatthew G. Knepley DM cdm, cdmCell = NULL; 15796858538eSMatthew G. Knepley PetscSection cs, csCell = NULL; 15806858538eSMatthew G. Knepley Vec coordinates, coordinatesCell; 15810444adf6SMatthew G. Knepley DMLabel cellSets = NULL, faceSets = NULL, edgeSets = NULL, vertSets = NULL, marker = NULL, *regionSets; 15829db5b827SMatthew G. Knepley PetscInt dim = 0, coordDim = -1, order = 0, maxHeight = 0; 15839db5b827SMatthew G. Knepley PetscInt numNodes = 0, numElems = 0, numVerts = 0, numCells = 0, vStart, vEnd; 1584066ea43fSLisandro Dalcin PetscInt cell, cone[8], e, n, v, d; 15852b205333SMatthew G. Knepley PetscBool usegeneric = PETSC_TRUE, useregions = PETSC_FALSE, markvertices = PETSC_FALSE, multipleTags = PETSC_FALSE; 15862b205333SMatthew G. Knepley PetscBool flg, binary, hybrid = interpolate, periodic = PETSC_TRUE; 1587066ea43fSLisandro Dalcin PetscBool highOrder = PETSC_TRUE, highOrderSet, project = PETSC_FALSE; 1588066ea43fSLisandro Dalcin PetscBool isSimplex = PETSC_FALSE, isHybrid = PETSC_FALSE, hasTetra = PETSC_FALSE; 15890598e1a2SLisandro Dalcin PetscMPIInt rank; 1590331830f3SMatthew G. Knepley 1591331830f3SMatthew G. Knepley PetscFunctionBegin; 15929566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1593d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)viewer); 1594d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Gmsh options"); 1595df93260fSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_gmsh_hybrid", "Force triangular prisms to use tensor order", "DMPlexCreateGmsh", hybrid, &hybrid, NULL)); 15969566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_periodic", "Read Gmsh periodic section", "DMPlexCreateGmsh", periodic, &periodic, NULL)); 15979566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_highorder", "Generate high-order coordinates", "DMPlexCreateGmsh", highOrder, &highOrder, &highOrderSet)); 15989566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_project", "Project high-order coordinates to a different space", "DMPlexCreateGmsh", project, &project, NULL)); 15999566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_use_regions", "Generate labels with region names", "DMPlexCreateGmsh", useregions, &useregions, NULL)); 16002b205333SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_gmsh_use_generic", "Generate generic labels, i.e. Cell Sets, Face Sets, etc", "DMPlexCreateGmsh", usegeneric, &usegeneric, &flg)); 16012b205333SMatthew G. Knepley if (!flg && useregions) usegeneric = PETSC_FALSE; 16029566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_mark_vertices", "Add vertices to generated labels", "DMPlexCreateGmsh", markvertices, &markvertices, NULL)); 1603df93260fSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_gmsh_multiple_tags", "Allow multiple tags for default labels", "DMPlexCreateGmsh", multipleTags, &multipleTags, NULL)); 16049566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_gmsh_spacedim", "Embedding space dimension", "DMPlexCreateGmsh", coordDim, &coordDim, NULL, PETSC_DECIDE)); 16059db5b827SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_localize_height", "Localize edges and faces in addition to cells", "", maxHeight, &maxHeight, NULL, 0)); 1606d0609cedSBarry Smith PetscOptionsHeadEnd(); 1607d0609cedSBarry Smith PetscOptionsEnd(); 16080598e1a2SLisandro Dalcin 16099566063dSJacob Faibussowitsch PetscCall(GmshCellInfoSetUp()); 161011c56cb0SLisandro Dalcin 16119566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 16129566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 16139566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CreateGmsh, *dm, NULL, NULL, NULL)); 161411c56cb0SLisandro Dalcin 16159566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &binary)); 161611c56cb0SLisandro Dalcin 161711c56cb0SLisandro Dalcin /* Binary viewers read on all ranks, get subviewer to read only in rank 0 */ 16183b46f529SLisandro Dalcin if (binary) { 161911c56cb0SLisandro Dalcin parentviewer = viewer; 16209566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(parentviewer, PETSC_COMM_SELF, &viewer)); 162111c56cb0SLisandro Dalcin } 162211c56cb0SLisandro Dalcin 1623dd400576SPatrick Sanan if (rank == 0) { 16240598e1a2SLisandro Dalcin GmshFile gmsh[1]; 1625698a79b9SLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 1626698a79b9SLisandro Dalcin PetscBool match; 1627331830f3SMatthew G. Knepley 16289566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(gmsh, 1)); 1629698a79b9SLisandro Dalcin gmsh->viewer = viewer; 1630698a79b9SLisandro Dalcin gmsh->binary = binary; 1631698a79b9SLisandro Dalcin 16329566063dSJacob Faibussowitsch PetscCall(GmshMeshCreate(&mesh)); 16330598e1a2SLisandro Dalcin 1634698a79b9SLisandro Dalcin /* Read mesh format */ 16359566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 16369566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$MeshFormat", line)); 16379566063dSJacob Faibussowitsch PetscCall(GmshReadMeshFormat(gmsh)); 16389566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndMeshFormat", line)); 163911c56cb0SLisandro Dalcin 16408749820aSMatthew G. Knepley /* OPTIONAL Read mesh version (Neper only) */ 16419566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 16428749820aSMatthew G. Knepley PetscCall(GmshMatch(gmsh, "$MeshVersion", line, &match)); 16438749820aSMatthew G. Knepley if (match) { 16448749820aSMatthew G. Knepley PetscCall(GmshExpect(gmsh, "$MeshVersion", line)); 16458749820aSMatthew G. Knepley PetscCall(GmshReadMeshVersion(gmsh)); 16468749820aSMatthew G. Knepley PetscCall(GmshReadEndSection(gmsh, "$EndMeshVersion", line)); 16478749820aSMatthew G. Knepley /* Initial read for entity section */ 16488749820aSMatthew G. Knepley PetscCall(GmshReadSection(gmsh, line)); 16498749820aSMatthew G. Knepley } 16508749820aSMatthew G. Knepley 16518749820aSMatthew G. Knepley /* OPTIONAL Read mesh domain (Neper only) */ 16528749820aSMatthew G. Knepley PetscCall(GmshMatch(gmsh, "$Domain", line, &match)); 16538749820aSMatthew G. Knepley if (match) { 16548749820aSMatthew G. Knepley PetscCall(GmshExpect(gmsh, "$Domain", line)); 16558749820aSMatthew G. Knepley PetscCall(GmshReadMeshDomain(gmsh)); 16568749820aSMatthew G. Knepley PetscCall(GmshReadEndSection(gmsh, "$EndDomain", line)); 16578749820aSMatthew G. Knepley /* Initial read for entity section */ 16588749820aSMatthew G. Knepley PetscCall(GmshReadSection(gmsh, line)); 16598749820aSMatthew G. Knepley } 16608749820aSMatthew G. Knepley 16618749820aSMatthew G. Knepley /* OPTIONAL Read physical names */ 16629566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, "$PhysicalNames", line, &match)); 1663dc0ede3bSMatthew G. Knepley if (match) { 16649566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$PhysicalNames", line)); 16659566063dSJacob Faibussowitsch PetscCall(GmshReadPhysicalNames(gmsh, mesh)); 16669566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndPhysicalNames", line)); 1667698a79b9SLisandro Dalcin /* Initial read for entity section */ 16689566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 1669dc0ede3bSMatthew G. Knepley } 167011c56cb0SLisandro Dalcin 1671e43c9757SMatthew G. Knepley /* OPTIONAL Read entities */ 1672698a79b9SLisandro Dalcin if (gmsh->fileFormat >= 40) { 1673e43c9757SMatthew G. Knepley PetscCall(GmshMatch(gmsh, "$Entities", line, &match)); 1674e43c9757SMatthew G. Knepley if (match) { 16759566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$Entities", line)); 16769566063dSJacob Faibussowitsch PetscCall(GmshReadEntities(gmsh, mesh)); 16779566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndEntities", line)); 1678698a79b9SLisandro Dalcin /* Initial read for nodes section */ 16799566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 1680de78e4feSLisandro Dalcin } 1681e43c9757SMatthew G. Knepley } 1682de78e4feSLisandro Dalcin 1683698a79b9SLisandro Dalcin /* Read nodes */ 16849566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$Nodes", line)); 16859566063dSJacob Faibussowitsch PetscCall(GmshReadNodes(gmsh, mesh)); 16869566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndNodes", line)); 168711c56cb0SLisandro Dalcin 1688698a79b9SLisandro Dalcin /* Read elements */ 16899566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 16909566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$Elements", line)); 16919566063dSJacob Faibussowitsch PetscCall(GmshReadElements(gmsh, mesh)); 16929566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndElements", line)); 1693de78e4feSLisandro Dalcin 16940598e1a2SLisandro Dalcin /* Read periodic section (OPTIONAL) */ 1695698a79b9SLisandro Dalcin if (periodic) { 16969566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 16979566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, "$Periodic", line, &periodic)); 1698ef12879bSLisandro Dalcin } 1699ef12879bSLisandro Dalcin if (periodic) { 17009566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$Periodic", line)); 17019566063dSJacob Faibussowitsch PetscCall(GmshReadPeriodic(gmsh, mesh)); 17029566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndPeriodic", line)); 1703698a79b9SLisandro Dalcin } 1704698a79b9SLisandro Dalcin 17059566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->wbuf)); 17069566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->sbuf)); 17079566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->nbuf)); 17080598e1a2SLisandro Dalcin 17090598e1a2SLisandro Dalcin dim = mesh->dim; 1710066ea43fSLisandro Dalcin order = mesh->order; 17110598e1a2SLisandro Dalcin numNodes = mesh->numNodes; 17120598e1a2SLisandro Dalcin numElems = mesh->numElems; 17130598e1a2SLisandro Dalcin numVerts = mesh->numVerts; 17140598e1a2SLisandro Dalcin numCells = mesh->numCells; 1715066ea43fSLisandro Dalcin 1716066ea43fSLisandro Dalcin { 1717066ea43fSLisandro Dalcin GmshElement *elemA = mesh->numCells > 0 ? mesh->elements : NULL; 17188e3a54c0SPierre Jolivet GmshElement *elemB = PetscSafePointerPlusOffset(elemA, mesh->numCells - 1); 1719066ea43fSLisandro Dalcin int ptA = elemA ? GmshCellMap[elemA->cellType].polytope : -1; 1720066ea43fSLisandro Dalcin int ptB = elemB ? GmshCellMap[elemB->cellType].polytope : -1; 1721066ea43fSLisandro Dalcin isSimplex = (ptA == GMSH_QUA || ptA == GMSH_HEX) ? PETSC_FALSE : PETSC_TRUE; 1722066ea43fSLisandro Dalcin isHybrid = (ptA == ptB) ? PETSC_FALSE : PETSC_TRUE; 1723066ea43fSLisandro Dalcin hasTetra = (ptA == GMSH_TET) ? PETSC_TRUE : PETSC_FALSE; 1724066ea43fSLisandro Dalcin } 1725698a79b9SLisandro Dalcin } 1726698a79b9SLisandro Dalcin 172748a46eb9SPierre Jolivet if (parentviewer) PetscCall(PetscViewerRestoreSubViewer(parentviewer, PETSC_COMM_SELF, &viewer)); 1728698a79b9SLisandro Dalcin 1729066ea43fSLisandro Dalcin { 1730066ea43fSLisandro Dalcin int buf[6]; 1731698a79b9SLisandro Dalcin 1732066ea43fSLisandro Dalcin buf[0] = (int)dim; 1733066ea43fSLisandro Dalcin buf[1] = (int)order; 1734066ea43fSLisandro Dalcin buf[2] = periodic; 1735066ea43fSLisandro Dalcin buf[3] = isSimplex; 1736066ea43fSLisandro Dalcin buf[4] = isHybrid; 1737066ea43fSLisandro Dalcin buf[5] = hasTetra; 1738066ea43fSLisandro Dalcin 17399566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(buf, 6, MPI_INT, 0, comm)); 1740066ea43fSLisandro Dalcin 1741066ea43fSLisandro Dalcin dim = buf[0]; 1742066ea43fSLisandro Dalcin order = buf[1]; 1743066ea43fSLisandro Dalcin periodic = buf[2] ? PETSC_TRUE : PETSC_FALSE; 1744066ea43fSLisandro Dalcin isSimplex = buf[3] ? PETSC_TRUE : PETSC_FALSE; 1745066ea43fSLisandro Dalcin isHybrid = buf[4] ? PETSC_TRUE : PETSC_FALSE; 1746066ea43fSLisandro Dalcin hasTetra = buf[5] ? PETSC_TRUE : PETSC_FALSE; 1747dea2a3c7SStefano Zampini } 1748dea2a3c7SStefano Zampini 1749066ea43fSLisandro Dalcin if (!highOrderSet) highOrder = (order > 1) ? PETSC_TRUE : PETSC_FALSE; 175008401ef6SPierre Jolivet PetscCheck(!highOrder || !isHybrid, comm, PETSC_ERR_SUP, "No support for discretization on hybrid meshes yet"); 1751066ea43fSLisandro Dalcin 17520598e1a2SLisandro Dalcin /* We do not want this label automatically computed, instead we fill it here */ 17539566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "celltype")); 175411c56cb0SLisandro Dalcin 1755a4bb7517SMichael Lange /* Allocate the cell-vertex mesh */ 17569566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(*dm, 0, numCells + numVerts)); 17570598e1a2SLisandro Dalcin for (cell = 0; cell < numCells; ++cell) { 17580598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + cell; 17590598e1a2SLisandro Dalcin DMPolytopeType ctype = DMPolytopeTypeFromGmsh(elem->cellType); 17600598e1a2SLisandro Dalcin if (hybrid && hasTetra && ctype == DM_POLYTOPE_TRI_PRISM) ctype = DM_POLYTOPE_TRI_PRISM_TENSOR; 17619566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(*dm, cell, elem->numVerts)); 17629566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(*dm, cell, ctype)); 1763db397164SMichael Lange } 176448a46eb9SPierre Jolivet for (v = numCells; v < numCells + numVerts; ++v) PetscCall(DMPlexSetCellType(*dm, v, DM_POLYTOPE_POINT)); 17659566063dSJacob Faibussowitsch PetscCall(DMSetUp(*dm)); 176696ca5757SLisandro Dalcin 1767a4bb7517SMichael Lange /* Add cell-vertex connections */ 17680598e1a2SLisandro Dalcin for (cell = 0; cell < numCells; ++cell) { 17690598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + cell; 17700598e1a2SLisandro Dalcin for (v = 0; v < elem->numVerts; ++v) { 17710598e1a2SLisandro Dalcin const PetscInt nn = elem->nodes[v]; 17720598e1a2SLisandro Dalcin const PetscInt vv = mesh->vertexMap[nn]; 17730598e1a2SLisandro Dalcin cone[v] = numCells + vv; 1774db397164SMichael Lange } 17759566063dSJacob Faibussowitsch PetscCall(DMPlexReorderCell(*dm, cell, cone)); 17769566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(*dm, cell, cone)); 1777a4bb7517SMichael Lange } 177896ca5757SLisandro Dalcin 17799566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 17809566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(*dm)); 17819566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(*dm)); 1782331830f3SMatthew G. Knepley if (interpolate) { 17835fd9971aSMatthew G. Knepley DM idm; 1784331830f3SMatthew G. Knepley 17859566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 17869566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 1787331830f3SMatthew G. Knepley *dm = idm; 1788331830f3SMatthew G. Knepley } 17899db5b827SMatthew G. Knepley PetscCall(DMPlexGetDepthStratum(*dm, 0, &vStart, &vEnd)); 1790917266a4SLisandro Dalcin 1791dd400576SPatrick Sanan if (rank == 0) { 1792a45dabc8SMatthew G. Knepley const PetscInt Nr = useregions ? mesh->numRegions : 0; 1793d1a54cefSMatthew G. Knepley 17949566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(Nr, ®ionSets)); 17950598e1a2SLisandro Dalcin for (cell = 0, e = 0; e < numElems; ++e) { 17960598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + e; 17976e1dd89aSLawrence Mitchell 17986e1dd89aSLawrence Mitchell /* Create cell sets */ 17990598e1a2SLisandro Dalcin if (elem->dim == dim && dim > 0) { 18000598e1a2SLisandro Dalcin if (elem->numTags > 0) { 1801df93260fSMatthew G. Knepley PetscInt Nt = elem->numTags, t, r; 1802a45dabc8SMatthew G. Knepley 1803df93260fSMatthew G. Knepley for (t = 0; t < Nt; ++t) { 1804df93260fSMatthew G. Knepley const PetscInt tag = elem->tags[t]; 18052b205333SMatthew G. Knepley const PetscBool generic = usegeneric && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE; 1806df93260fSMatthew G. Knepley 1807df93260fSMatthew G. Knepley if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &cellSets, "Cell Sets", cell, tag)); 1808a45dabc8SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 1809df93260fSMatthew G. Knepley if (mesh->regionDims[r] != dim) continue; 18109566063dSJacob Faibussowitsch if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], cell, tag)); 1811a45dabc8SMatthew G. Knepley } 18126e1dd89aSLawrence Mitchell } 1813df93260fSMatthew G. Knepley } 1814917266a4SLisandro Dalcin cell++; 18156e1dd89aSLawrence Mitchell } 18160c070f12SSander Arens 18170598e1a2SLisandro Dalcin /* Create face sets */ 1818aec57b10SMatthew G. Knepley if (elem->numTags && interpolate && elem->dim == dim - 1) { 18190598e1a2SLisandro Dalcin PetscInt joinSize; 18200598e1a2SLisandro Dalcin const PetscInt *join = NULL; 18210444adf6SMatthew G. Knepley PetscInt Nt = elem->numTags, pdepth; 1822a45dabc8SMatthew G. Knepley 18230598e1a2SLisandro Dalcin /* Find the relevant facet with vertex joins */ 18240598e1a2SLisandro Dalcin for (v = 0; v < elem->numVerts; ++v) { 18250598e1a2SLisandro Dalcin const PetscInt nn = elem->nodes[v]; 18260598e1a2SLisandro Dalcin const PetscInt vv = mesh->vertexMap[nn]; 18270598e1a2SLisandro Dalcin cone[v] = vStart + vv; 18280598e1a2SLisandro Dalcin } 18299566063dSJacob Faibussowitsch PetscCall(DMPlexGetFullJoin(*dm, elem->numVerts, cone, &joinSize, &join)); 183063a3b9bcSJacob 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); 18310444adf6SMatthew G. Knepley PetscCall(DMPlexGetPointDepth(*dm, join[0], &pdepth)); 18320444adf6SMatthew 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); 18330444adf6SMatthew G. Knepley for (PetscInt t = 0; t < Nt; ++t) { 18345ad74b4fSMatthew G. Knepley const PetscInt tag = elem->tags[t]; 18352b205333SMatthew G. Knepley const PetscBool generic = usegeneric && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE; 18365ad74b4fSMatthew G. Knepley 1837df93260fSMatthew G. Knepley if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &faceSets, "Face Sets", join[0], tag)); 18380444adf6SMatthew G. Knepley for (PetscInt r = 0; r < Nr; ++r) { 1839df93260fSMatthew G. Knepley if (mesh->regionDims[r] != dim - 1) continue; 18409566063dSJacob Faibussowitsch if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], join[0], tag)); 1841a45dabc8SMatthew G. Knepley } 18425ad74b4fSMatthew G. Knepley } 18439566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(*dm, elem->numVerts, cone, &joinSize, &join)); 18440598e1a2SLisandro Dalcin } 18450598e1a2SLisandro Dalcin 1846aec57b10SMatthew G. Knepley /* Create edge sets */ 1847aec57b10SMatthew G. Knepley if (elem->numTags && interpolate && dim > 2 && elem->dim == 1) { 1848aec57b10SMatthew G. Knepley PetscInt joinSize; 1849aec57b10SMatthew G. Knepley const PetscInt *join = NULL; 1850aec57b10SMatthew G. Knepley PetscInt Nt = elem->numTags, t, r; 1851aec57b10SMatthew G. Knepley 1852aec57b10SMatthew G. Knepley /* Find the relevant edge with vertex joins */ 1853aec57b10SMatthew G. Knepley for (v = 0; v < elem->numVerts; ++v) { 1854aec57b10SMatthew G. Knepley const PetscInt nn = elem->nodes[v]; 1855aec57b10SMatthew G. Knepley const PetscInt vv = mesh->vertexMap[nn]; 1856aec57b10SMatthew G. Knepley cone[v] = vStart + vv; 1857aec57b10SMatthew G. Knepley } 1858aec57b10SMatthew G. Knepley PetscCall(DMPlexGetJoin(*dm, elem->numVerts, cone, &joinSize, &join)); 1859aec57b10SMatthew 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); 1860aec57b10SMatthew G. Knepley for (t = 0; t < Nt; ++t) { 1861aec57b10SMatthew G. Knepley const PetscInt tag = elem->tags[t]; 18622b205333SMatthew G. Knepley const PetscBool generic = usegeneric && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE; 1863aec57b10SMatthew G. Knepley 18640444adf6SMatthew G. Knepley if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &edgeSets, "Edge Sets", join[0], tag)); 1865aec57b10SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 1866aec57b10SMatthew G. Knepley if (mesh->regionDims[r] != 1) continue; 1867aec57b10SMatthew G. Knepley if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], join[0], tag)); 1868aec57b10SMatthew G. Knepley } 1869aec57b10SMatthew G. Knepley } 1870aec57b10SMatthew G. Knepley PetscCall(DMPlexRestoreJoin(*dm, elem->numVerts, cone, &joinSize, &join)); 1871aec57b10SMatthew G. Knepley } 1872aec57b10SMatthew G. Knepley 18730c070f12SSander Arens /* Create vertex sets */ 1874aec57b10SMatthew G. Knepley if (elem->numTags && elem->dim == 0 && markvertices) { 18750598e1a2SLisandro Dalcin const PetscInt nn = elem->nodes[0]; 18760598e1a2SLisandro Dalcin const PetscInt vv = mesh->vertexMap[nn]; 1877a45dabc8SMatthew G. Knepley const PetscInt tag = elem->tags[0]; 1878a45dabc8SMatthew G. Knepley PetscInt r; 1879a45dabc8SMatthew G. Knepley 18808a3d9825SMatthew G. Knepley if (vv < 0) continue; 18812b205333SMatthew G. Knepley if (usegeneric) PetscCall(DMSetLabelValue_Fast(*dm, &vertSets, "Vertex Sets", vStart + vv, tag)); 188281a1af93SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 1883df93260fSMatthew G. Knepley if (mesh->regionDims[r] != 0) continue; 18849566063dSJacob Faibussowitsch if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], vStart + vv, tag)); 188581a1af93SMatthew G. Knepley } 188681a1af93SMatthew G. Knepley } 188781a1af93SMatthew G. Knepley } 188881a1af93SMatthew G. Knepley if (markvertices) { 188981a1af93SMatthew G. Knepley for (v = 0; v < numNodes; ++v) { 189081a1af93SMatthew G. Knepley const PetscInt vv = mesh->vertexMap[v]; 18917d5b9244SMatthew G. Knepley const PetscInt *tags = &mesh->nodelist->tag[v * GMSH_MAX_TAGS]; 18927d5b9244SMatthew G. Knepley PetscInt r, t; 189381a1af93SMatthew G. Knepley 18948a3d9825SMatthew G. Knepley if (vv < 0) continue; 18957d5b9244SMatthew G. Knepley for (t = 0; t < GMSH_MAX_TAGS; ++t) { 18967d5b9244SMatthew G. Knepley const PetscInt tag = tags[t]; 18972b205333SMatthew G. Knepley const PetscBool generic = usegeneric && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE; 18987d5b9244SMatthew G. Knepley 18997d5b9244SMatthew G. Knepley if (tag == -1) continue; 1900df93260fSMatthew G. Knepley if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &vertSets, "Vertex Sets", vStart + vv, tag)); 1901a45dabc8SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 19029566063dSJacob Faibussowitsch if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], vStart + vv, tag)); 19030598e1a2SLisandro Dalcin } 19040598e1a2SLisandro Dalcin } 19050598e1a2SLisandro Dalcin } 19060598e1a2SLisandro Dalcin } 19079566063dSJacob Faibussowitsch PetscCall(PetscFree(regionSets)); 1908a45dabc8SMatthew G. Knepley } 19090598e1a2SLisandro Dalcin 19100444adf6SMatthew G. Knepley { /* Create Cell/Face/Edge/Vertex Sets labels at all processes */ 19119371c9d4SSatish Balay enum { 19120444adf6SMatthew G. Knepley n = 5 19139371c9d4SSatish Balay }; 19147dd454faSLisandro Dalcin PetscBool flag[n]; 19157dd454faSLisandro Dalcin 19167dd454faSLisandro Dalcin flag[0] = cellSets ? PETSC_TRUE : PETSC_FALSE; 19177dd454faSLisandro Dalcin flag[1] = faceSets ? PETSC_TRUE : PETSC_FALSE; 19180444adf6SMatthew G. Knepley flag[2] = edgeSets ? PETSC_TRUE : PETSC_FALSE; 19190444adf6SMatthew G. Knepley flag[3] = vertSets ? PETSC_TRUE : PETSC_FALSE; 19200444adf6SMatthew G. Knepley flag[4] = marker ? PETSC_TRUE : PETSC_FALSE; 19219566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(flag, n, MPIU_BOOL, 0, comm)); 19229566063dSJacob Faibussowitsch if (flag[0]) PetscCall(DMCreateLabel(*dm, "Cell Sets")); 19239566063dSJacob Faibussowitsch if (flag[1]) PetscCall(DMCreateLabel(*dm, "Face Sets")); 19240444adf6SMatthew G. Knepley if (flag[2]) PetscCall(DMCreateLabel(*dm, "Edge Sets")); 19250444adf6SMatthew G. Knepley if (flag[3]) PetscCall(DMCreateLabel(*dm, "Vertex Sets")); 19260444adf6SMatthew G. Knepley if (flag[4]) PetscCall(DMCreateLabel(*dm, "marker")); 19277dd454faSLisandro Dalcin } 19287dd454faSLisandro Dalcin 19290598e1a2SLisandro Dalcin if (periodic) { 19309566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(numVerts, &periodicVerts)); 19310598e1a2SLisandro Dalcin for (n = 0; n < numNodes; ++n) { 19320598e1a2SLisandro Dalcin if (mesh->vertexMap[n] >= 0) { 19330598e1a2SLisandro Dalcin if (PetscUnlikely(mesh->periodMap[n] != n)) { 19340598e1a2SLisandro Dalcin PetscInt m = mesh->periodMap[n]; 19359566063dSJacob Faibussowitsch PetscCall(PetscBTSet(periodicVerts, mesh->vertexMap[n])); 19369566063dSJacob Faibussowitsch PetscCall(PetscBTSet(periodicVerts, mesh->vertexMap[m])); 19370598e1a2SLisandro Dalcin } 19380598e1a2SLisandro Dalcin } 19390598e1a2SLisandro Dalcin } 19409db5b827SMatthew G. Knepley PetscCall(DMGetCoordinateDM(*dm, &cdm)); 1941eae3dc7dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxHeight + 1, &periodicCells)); 19429db5b827SMatthew G. Knepley for (PetscInt h = 0; h <= maxHeight; ++h) { 19439db5b827SMatthew G. Knepley PetscInt pStart, pEnd; 19449db5b827SMatthew G. Knepley 19459db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(*dm, h, &pStart, &pEnd)); 19469db5b827SMatthew G. Knepley PetscCall(PetscBTCreate(pEnd - pStart, &periodicCells[h])); 19479db5b827SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 19489db5b827SMatthew G. Knepley PetscInt *closure = NULL; 19499db5b827SMatthew G. Knepley PetscInt Ncl; 19509db5b827SMatthew G. Knepley 19519db5b827SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure)); 19529db5b827SMatthew G. Knepley for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) { 19539db5b827SMatthew G. Knepley if (closure[cl] >= vStart && closure[cl] < vEnd) { 19549db5b827SMatthew G. Knepley if (PetscUnlikely(PetscBTLookup(periodicVerts, closure[cl] - vStart))) { 19559db5b827SMatthew G. Knepley PetscCall(PetscBTSet(periodicCells[h], p - pStart)); 19569371c9d4SSatish Balay break; 19570c070f12SSander Arens } 19580c070f12SSander Arens } 19590c070f12SSander Arens } 19609db5b827SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure)); 19619db5b827SMatthew G. Knepley } 19629db5b827SMatthew G. Knepley } 196316ad7e67SMichael Lange } 196416ad7e67SMichael Lange 1965066ea43fSLisandro Dalcin /* Setup coordinate DM */ 19660598e1a2SLisandro Dalcin if (coordDim < 0) coordDim = dim; 19679566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(*dm, coordDim)); 19689566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(*dm, &cdm)); 1969066ea43fSLisandro Dalcin if (highOrder) { 1970066ea43fSLisandro Dalcin PetscFE fe; 1971066ea43fSLisandro Dalcin PetscBool continuity = periodic ? PETSC_FALSE : PETSC_TRUE; 1972066ea43fSLisandro Dalcin PetscDTNodeType nodeType = PETSCDTNODES_EQUISPACED; 1973066ea43fSLisandro Dalcin 1974066ea43fSLisandro Dalcin if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */ 1975066ea43fSLisandro Dalcin 19769566063dSJacob Faibussowitsch PetscCall(GmshCreateFE(comm, NULL, isSimplex, continuity, nodeType, dim, coordDim, order, &fe)); 19779566063dSJacob Faibussowitsch PetscCall(PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_fe_view")); 19789566063dSJacob Faibussowitsch PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)fe)); 19799566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 19809566063dSJacob Faibussowitsch PetscCall(DMCreateDS(cdm)); 1981066ea43fSLisandro Dalcin } 19826858538eSMatthew G. Knepley if (periodic) { 19836858538eSMatthew G. Knepley PetscCall(DMClone(cdm, &cdmCell)); 19846858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(*dm, cdmCell)); 19856858538eSMatthew G. Knepley } 1986066ea43fSLisandro Dalcin 1987066ea43fSLisandro Dalcin /* Create coordinates */ 1988066ea43fSLisandro Dalcin if (highOrder) { 1989066ea43fSLisandro Dalcin PetscInt maxDof = GmshNumNodes_HEX(order) * coordDim; 1990066ea43fSLisandro Dalcin double *coords = mesh ? mesh->nodelist->xyz : NULL; 1991066ea43fSLisandro Dalcin PetscSection section; 1992066ea43fSLisandro Dalcin PetscScalar *cellCoords; 1993066ea43fSLisandro Dalcin 19949566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(cdm, NULL)); 19956858538eSMatthew G. Knepley PetscCall(DMGetLocalSection(cdm, &cs)); 19966858538eSMatthew G. Knepley PetscCall(PetscSectionClone(cs, §ion)); 19979566063dSJacob Faibussowitsch PetscCall(DMPlexSetClosurePermutationTensor(cdm, 0, section)); /* XXX Implement DMPlexSetClosurePermutationLexicographic() */ 1998066ea43fSLisandro Dalcin 19999566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(cdm, &coordinates)); 20009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof, &cellCoords)); 2001066ea43fSLisandro Dalcin for (cell = 0; cell < numCells; ++cell) { 2002066ea43fSLisandro Dalcin GmshElement *elem = mesh->elements + cell; 2003066ea43fSLisandro Dalcin const int *lexorder = GmshCellMap[elem->cellType].lexorder(); 2004b9bf55e5SMatthew G. Knepley int s = 0; 2005066ea43fSLisandro Dalcin for (n = 0; n < elem->numNodes; ++n) { 2006b9bf55e5SMatthew G. Knepley while (lexorder[n + s] < 0) ++s; 2007b9bf55e5SMatthew G. Knepley const PetscInt node = elem->nodes[lexorder[n + s]]; 2008b9bf55e5SMatthew G. Knepley for (d = 0; d < coordDim; ++d) cellCoords[(n + s) * coordDim + d] = (PetscReal)coords[node * 3 + d]; 2009b9bf55e5SMatthew G. Knepley } 2010b9bf55e5SMatthew G. Knepley if (s) { 2011b9bf55e5SMatthew G. Knepley /* For the coordinate mapping we weight vertices by -1/4 and edges by 1/2, which we get from Q_2 interpolation */ 2012b9bf55e5SMatthew G. Knepley PetscReal quaCenterWeights[9] = {-0.25, 0.5, -0.25, 0.5, 0.0, 0.5, -0.25, 0.5, -0.25}; 2013b9bf55e5SMatthew G. Knepley /* For the coordinate mapping we weight vertices by -1/4 and edges by 1/2, which we get from Q_2 interpolation */ 20149371c9d4SSatish 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}; 20159371c9d4SSatish 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}; 20169371c9d4SSatish 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}; 20179371c9d4SSatish 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}; 20189371c9d4SSatish 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}; 20199371c9d4SSatish 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}; 20209371c9d4SSatish 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}; 2021b9bf55e5SMatthew G. Knepley PetscReal *sdWeights2[9] = {NULL, NULL, NULL, NULL, quaCenterWeights, NULL, NULL, NULL, NULL}; 20229371c9d4SSatish Balay PetscReal *sdWeights3[27] = {NULL, NULL, NULL, NULL, hexBottomWeights, NULL, NULL, NULL, NULL, NULL, hexFrontWeights, NULL, hexLeftWeights, hexCenterWeights, hexRightWeights, NULL, hexBackWeights, NULL, 2023b9bf55e5SMatthew G. Knepley NULL, NULL, NULL, NULL, hexTopWeights, NULL, NULL, NULL, NULL}; 2024b9bf55e5SMatthew G. Knepley PetscReal **sdWeights[4] = {NULL, NULL, sdWeights2, sdWeights3}; 2025b9bf55e5SMatthew G. Knepley 2026b9bf55e5SMatthew G. Knepley /* Missing entries in serendipity cell, only works for 8-node quad and 20-node hex */ 2027b9bf55e5SMatthew G. Knepley for (n = 0; n < elem->numNodes + s; ++n) { 2028b9bf55e5SMatthew G. Knepley if (lexorder[n] >= 0) continue; 2029b9bf55e5SMatthew G. Knepley for (d = 0; d < coordDim; ++d) cellCoords[n * coordDim + d] = 0.0; 2030b9bf55e5SMatthew G. Knepley for (int bn = 0; bn < elem->numNodes + s; ++bn) { 2031b9bf55e5SMatthew G. Knepley if (lexorder[bn] < 0) continue; 2032b9bf55e5SMatthew G. Knepley const PetscReal *weights = sdWeights[coordDim][n]; 2033b9bf55e5SMatthew G. Knepley const PetscInt bnode = elem->nodes[lexorder[bn]]; 2034b9bf55e5SMatthew G. Knepley for (d = 0; d < coordDim; ++d) cellCoords[n * coordDim + d] += weights[bn] * (PetscReal)coords[bnode * 3 + d]; 2035b9bf55e5SMatthew G. Knepley } 2036b9bf55e5SMatthew G. Knepley } 2037066ea43fSLisandro Dalcin } 20389566063dSJacob Faibussowitsch PetscCall(DMPlexVecSetClosure(cdm, section, coordinates, cell, cellCoords, INSERT_VALUES)); 2039066ea43fSLisandro Dalcin } 20409566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 20419566063dSJacob Faibussowitsch PetscCall(PetscFree(cellCoords)); 2042066ea43fSLisandro Dalcin } else { 2043066ea43fSLisandro Dalcin PetscInt *nodeMap; 2044066ea43fSLisandro Dalcin double *coords = mesh ? mesh->nodelist->xyz : NULL; 2045066ea43fSLisandro Dalcin PetscScalar *pointCoords; 2046066ea43fSLisandro Dalcin 20476858538eSMatthew G. Knepley PetscCall(DMGetCoordinateSection(*dm, &cs)); 20486858538eSMatthew G. Knepley PetscCall(PetscSectionSetNumFields(cs, 1)); 20496858538eSMatthew G. Knepley PetscCall(PetscSectionSetFieldComponents(cs, 0, coordDim)); 20506858538eSMatthew G. Knepley PetscCall(PetscSectionSetChart(cs, numCells, numCells + numVerts)); 20516858538eSMatthew G. Knepley for (v = numCells; v < numCells + numVerts; ++v) { 20526858538eSMatthew G. Knepley PetscCall(PetscSectionSetDof(cs, v, coordDim)); 20536858538eSMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(cs, v, 0, coordDim)); 2054f45c9589SStefano Zampini } 20556858538eSMatthew G. Knepley PetscCall(PetscSectionSetUp(cs)); 20566858538eSMatthew G. Knepley 20576858538eSMatthew G. Knepley /* We need to localize coordinates on cells */ 20580598e1a2SLisandro Dalcin if (periodic) { 2059*1690c2aeSBarry Smith PetscInt newStart = PETSC_INT_MAX, newEnd = -1, pStart, pEnd; 20609db5b827SMatthew G. Knepley 20616858538eSMatthew G. Knepley PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)cdmCell), &csCell)); 20626858538eSMatthew G. Knepley PetscCall(PetscSectionSetNumFields(csCell, 1)); 20636858538eSMatthew G. Knepley PetscCall(PetscSectionSetFieldComponents(csCell, 0, coordDim)); 20649db5b827SMatthew G. Knepley for (PetscInt h = 0; h <= maxHeight; h++) { 20659db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(cdmCell, h, &pStart, &pEnd)); 20669db5b827SMatthew G. Knepley newStart = PetscMin(newStart, pStart); 20679db5b827SMatthew G. Knepley newEnd = PetscMax(newEnd, pEnd); 20689db5b827SMatthew G. Knepley } 20699db5b827SMatthew G. Knepley PetscCall(PetscSectionSetChart(csCell, newStart, newEnd)); 20709db5b827SMatthew G. Knepley for (PetscInt h = 0; h <= maxHeight; h++) { 20719db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(cdmCell, h, &pStart, &pEnd)); 20729db5b827SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 20739db5b827SMatthew G. Knepley PetscInt *closure = NULL; 20749db5b827SMatthew G. Knepley PetscInt Ncl, Nv = 0; 20756858538eSMatthew G. Knepley 20769db5b827SMatthew G. Knepley if (PetscUnlikely(PetscBTLookup(periodicCells[h], p - pStart))) { 20779db5b827SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure)); 20789db5b827SMatthew G. Knepley for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) { 20799db5b827SMatthew G. Knepley if (closure[cl] >= vStart && closure[cl] < vEnd) ++Nv; 20809db5b827SMatthew G. Knepley } 20819db5b827SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure)); 20829db5b827SMatthew G. Knepley PetscCall(PetscSectionSetDof(csCell, p, Nv * coordDim)); 20839db5b827SMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(csCell, p, 0, Nv * coordDim)); 20849db5b827SMatthew G. Knepley } 2085f45c9589SStefano Zampini } 2086f45c9589SStefano Zampini } 20876858538eSMatthew G. Knepley PetscCall(PetscSectionSetUp(csCell)); 20886858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateSection(*dm, PETSC_DETERMINE, csCell)); 2089f45c9589SStefano Zampini } 2090066ea43fSLisandro Dalcin 20919566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(cdm, &coordinates)); 20929566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &pointCoords)); 20936858538eSMatthew G. Knepley PetscCall(PetscMalloc1(numVerts, &nodeMap)); 20946858538eSMatthew G. Knepley for (n = 0; n < numNodes; n++) 20956858538eSMatthew G. Knepley if (mesh->vertexMap[n] >= 0) nodeMap[mesh->vertexMap[n]] = n; 20966858538eSMatthew G. Knepley for (v = 0; v < numVerts; ++v) { 20976858538eSMatthew G. Knepley PetscInt off, node = nodeMap[v]; 20986858538eSMatthew G. Knepley 20996858538eSMatthew G. Knepley PetscCall(PetscSectionGetOffset(cs, numCells + v, &off)); 21006858538eSMatthew G. Knepley for (d = 0; d < coordDim; ++d) pointCoords[off + d] = (PetscReal)coords[node * 3 + d]; 21016858538eSMatthew G. Knepley } 21026858538eSMatthew G. Knepley PetscCall(VecRestoreArray(coordinates, &pointCoords)); 21036858538eSMatthew G. Knepley 21040598e1a2SLisandro Dalcin if (periodic) { 21059db5b827SMatthew G. Knepley PetscInt cStart, cEnd; 21069db5b827SMatthew G. Knepley 21079db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(cdmCell, 0, &cStart, &cEnd)); 21086858538eSMatthew G. Knepley PetscCall(DMCreateLocalVector(cdmCell, &coordinatesCell)); 21096858538eSMatthew G. Knepley PetscCall(VecGetArray(coordinatesCell, &pointCoords)); 21109db5b827SMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) { 21119db5b827SMatthew G. Knepley GmshElement *elem = mesh->elements + c - cStart; 21129db5b827SMatthew G. Knepley PetscInt *closure = NULL; 21139db5b827SMatthew G. Knepley PetscInt verts[8]; 21149db5b827SMatthew G. Knepley PetscInt Ncl, Nv = 0; 21159db5b827SMatthew G. Knepley 21169db5b827SMatthew G. Knepley for (PetscInt v = 0; v < elem->numVerts; ++v) cone[v] = elem->nodes[v]; 21179db5b827SMatthew G. Knepley PetscCall(DMPlexReorderCell(cdmCell, c, cone)); 21189db5b827SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(cdmCell, c, PETSC_TRUE, &Ncl, &closure)); 21199db5b827SMatthew G. Knepley for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) { 21209db5b827SMatthew G. Knepley if (closure[cl] >= vStart && closure[cl] < vEnd) verts[Nv++] = closure[cl]; 2121331830f3SMatthew G. Knepley } 21229db5b827SMatthew 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); 21239db5b827SMatthew G. Knepley for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) { 21249db5b827SMatthew G. Knepley const PetscInt point = closure[cl]; 21259db5b827SMatthew G. Knepley PetscInt hStart, h; 21269db5b827SMatthew G. Knepley 21279db5b827SMatthew G. Knepley PetscCall(DMPlexGetPointHeight(cdmCell, point, &h)); 21289db5b827SMatthew G. Knepley if (h > maxHeight) continue; 21299db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(cdmCell, h, &hStart, NULL)); 21309db5b827SMatthew G. Knepley if (PetscUnlikely(PetscBTLookup(periodicCells[h], point - hStart))) { 21319db5b827SMatthew G. Knepley PetscInt *pclosure = NULL; 21329db5b827SMatthew G. Knepley PetscInt Npcl, off, v; 21339db5b827SMatthew G. Knepley 21349db5b827SMatthew G. Knepley PetscCall(PetscSectionGetOffset(csCell, point, &off)); 21359db5b827SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(cdmCell, point, PETSC_TRUE, &Npcl, &pclosure)); 21369db5b827SMatthew G. Knepley for (PetscInt pcl = 0; pcl < Npcl * 2; pcl += 2) { 21379db5b827SMatthew G. Knepley if (pclosure[pcl] >= vStart && pclosure[pcl] < vEnd) { 21389db5b827SMatthew G. Knepley for (v = 0; v < Nv; ++v) 21399db5b827SMatthew G. Knepley if (verts[v] == pclosure[pcl]) break; 21409db5b827SMatthew 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); 21419db5b827SMatthew G. Knepley for (PetscInt d = 0; d < coordDim; ++d) pointCoords[off++] = (PetscReal)coords[cone[v] * 3 + d]; 21429db5b827SMatthew G. Knepley ++v; 21439db5b827SMatthew G. Knepley } 21449db5b827SMatthew G. Knepley } 21459db5b827SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(cdmCell, point, PETSC_TRUE, &Npcl, &pclosure)); 21469db5b827SMatthew G. Knepley } 21479db5b827SMatthew G. Knepley } 21489db5b827SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(cdmCell, c, PETSC_TRUE, &Ncl, &closure)); 2149331830f3SMatthew G. Knepley } 21506858538eSMatthew G. Knepley PetscCall(VecSetBlockSize(coordinatesCell, coordDim)); 21516858538eSMatthew G. Knepley PetscCall(VecRestoreArray(coordinatesCell, &pointCoords)); 21526858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(*dm, coordinatesCell)); 21536858538eSMatthew G. Knepley PetscCall(VecDestroy(&coordinatesCell)); 2154331830f3SMatthew G. Knepley } 21559db5b827SMatthew G. Knepley PetscCall(PetscFree(nodeMap)); 21566858538eSMatthew G. Knepley PetscCall(PetscSectionDestroy(&csCell)); 21576858538eSMatthew G. Knepley PetscCall(DMDestroy(&cdmCell)); 2158066ea43fSLisandro Dalcin } 2159066ea43fSLisandro Dalcin 21609566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 21619566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, coordDim)); 21629566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(*dm, coordinates)); 21639566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 216411c56cb0SLisandro Dalcin 21659566063dSJacob Faibussowitsch PetscCall(GmshMeshDestroy(&mesh)); 21669566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&periodicVerts)); 2167eae3dc7dSJacob Faibussowitsch if (periodic) { 2168eae3dc7dSJacob Faibussowitsch for (PetscInt h = 0; h <= maxHeight; ++h) PetscCall(PetscBTDestroy(periodicCells + h)); 2169eae3dc7dSJacob Faibussowitsch PetscCall(PetscFree(periodicCells)); 2170eae3dc7dSJacob Faibussowitsch } 217111c56cb0SLisandro Dalcin 2172066ea43fSLisandro Dalcin if (highOrder && project) { 2173066ea43fSLisandro Dalcin PetscFE fe; 2174066ea43fSLisandro Dalcin const char prefix[] = "dm_plex_gmsh_project_"; 2175066ea43fSLisandro Dalcin PetscBool continuity = periodic ? PETSC_FALSE : PETSC_TRUE; 2176066ea43fSLisandro Dalcin PetscDTNodeType nodeType = PETSCDTNODES_GAUSSJACOBI; 2177066ea43fSLisandro Dalcin 2178066ea43fSLisandro Dalcin if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */ 21799566063dSJacob Faibussowitsch PetscCall(GmshCreateFE(comm, prefix, isSimplex, continuity, nodeType, dim, coordDim, order, &fe)); 21809566063dSJacob Faibussowitsch PetscCall(PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_project_fe_view")); 2181e44f6aebSMatthew G. Knepley PetscCall(DMSetCoordinateDisc(*dm, fe, PETSC_TRUE)); 21829566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 2183066ea43fSLisandro Dalcin } 2184066ea43fSLisandro Dalcin 21859566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CreateGmsh, *dm, NULL, NULL, NULL)); 21863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2187331830f3SMatthew G. Knepley } 2188