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 120*10dd146fSPierre Jolivet // clang-format off 121*10dd146fSPierre Jolivet #define GmshCellEntry(cellType, polytope, dim, order) {cellType, GMSH_##polytope, dim, order, GmshNumNodes_##polytope(1), GmshNumNodes_##polytope(order), GmshLexOrder_##polytope##_##order} 122*10dd146fSPierre Jolivet // clang-format on 1230598e1a2SLisandro Dalcin 1240598e1a2SLisandro Dalcin static const GmshCellInfo GmshCellTable[] = { 125066ea43fSLisandro Dalcin GmshCellEntry(15, VTX, 0, 0), 1260598e1a2SLisandro Dalcin 1279371c9d4SSatish Balay GmshCellEntry(1, SEG, 1, 1), GmshCellEntry(8, SEG, 1, 2), GmshCellEntry(26, SEG, 1, 3), 1289371c9d4SSatish Balay GmshCellEntry(27, SEG, 1, 4), GmshCellEntry(28, SEG, 1, 5), GmshCellEntry(62, SEG, 1, 6), 1299371c9d4SSatish Balay GmshCellEntry(63, SEG, 1, 7), GmshCellEntry(64, SEG, 1, 8), GmshCellEntry(65, SEG, 1, 9), 130066ea43fSLisandro Dalcin GmshCellEntry(66, SEG, 1, 10), 1310598e1a2SLisandro Dalcin 1329371c9d4SSatish Balay GmshCellEntry(2, TRI, 2, 1), GmshCellEntry(9, TRI, 2, 2), GmshCellEntry(21, TRI, 2, 3), 1339371c9d4SSatish Balay GmshCellEntry(23, TRI, 2, 4), GmshCellEntry(25, TRI, 2, 5), GmshCellEntry(42, TRI, 2, 6), 1349371c9d4SSatish Balay GmshCellEntry(43, TRI, 2, 7), GmshCellEntry(44, TRI, 2, 8), GmshCellEntry(45, TRI, 2, 9), 135066ea43fSLisandro Dalcin GmshCellEntry(46, TRI, 2, 10), 1360598e1a2SLisandro Dalcin 1379371c9d4SSatish Balay GmshCellEntry(3, QUA, 2, 1), GmshCellEntry(10, QUA, 2, 2), {16, GMSH_QUA, 2, 2, 4, 8, GmshLexOrder_QUA_2_Serendipity}, 1389371c9d4SSatish Balay GmshCellEntry(36, QUA, 2, 3), GmshCellEntry(37, QUA, 2, 4), GmshCellEntry(38, QUA, 2, 5), 1399371c9d4SSatish Balay GmshCellEntry(47, QUA, 2, 6), GmshCellEntry(48, QUA, 2, 7), GmshCellEntry(49, QUA, 2, 8), 1409371c9d4SSatish Balay GmshCellEntry(50, QUA, 2, 9), GmshCellEntry(51, QUA, 2, 10), 1410598e1a2SLisandro Dalcin 1429371c9d4SSatish Balay GmshCellEntry(4, TET, 3, 1), GmshCellEntry(11, TET, 3, 2), GmshCellEntry(29, TET, 3, 3), 1439371c9d4SSatish Balay GmshCellEntry(30, TET, 3, 4), GmshCellEntry(31, TET, 3, 5), GmshCellEntry(71, TET, 3, 6), 1449371c9d4SSatish Balay GmshCellEntry(72, TET, 3, 7), GmshCellEntry(73, TET, 3, 8), GmshCellEntry(74, TET, 3, 9), 145066ea43fSLisandro Dalcin GmshCellEntry(75, TET, 3, 10), 1460598e1a2SLisandro Dalcin 1479371c9d4SSatish Balay GmshCellEntry(5, HEX, 3, 1), GmshCellEntry(12, HEX, 3, 2), {17, GMSH_HEX, 3, 2, 8, 20, GmshLexOrder_HEX_2_Serendipity}, 1489371c9d4SSatish Balay GmshCellEntry(92, HEX, 3, 3), GmshCellEntry(93, HEX, 3, 4), GmshCellEntry(94, HEX, 3, 5), 1499371c9d4SSatish Balay GmshCellEntry(95, HEX, 3, 6), GmshCellEntry(96, HEX, 3, 7), GmshCellEntry(97, HEX, 3, 8), 1509371c9d4SSatish Balay GmshCellEntry(98, HEX, 3, 9), GmshCellEntry(-1, HEX, 3, 10), 1510598e1a2SLisandro Dalcin 1529371c9d4SSatish Balay GmshCellEntry(6, PRI, 3, 1), GmshCellEntry(13, PRI, 3, 2), GmshCellEntry(90, PRI, 3, 3), 1539371c9d4SSatish Balay GmshCellEntry(91, PRI, 3, 4), GmshCellEntry(106, PRI, 3, 5), GmshCellEntry(107, PRI, 3, 6), 1549371c9d4SSatish Balay GmshCellEntry(108, PRI, 3, 7), GmshCellEntry(109, PRI, 3, 8), GmshCellEntry(110, PRI, 3, 9), 155066ea43fSLisandro Dalcin GmshCellEntry(-1, PRI, 3, 10), 1560598e1a2SLisandro Dalcin 1579371c9d4SSatish Balay GmshCellEntry(7, PYR, 3, 1), GmshCellEntry(14, PYR, 3, 2), GmshCellEntry(118, PYR, 3, 3), 1589371c9d4SSatish Balay GmshCellEntry(119, PYR, 3, 4), GmshCellEntry(120, PYR, 3, 5), GmshCellEntry(121, PYR, 3, 6), 1599371c9d4SSatish Balay GmshCellEntry(122, PYR, 3, 7), GmshCellEntry(123, PYR, 3, 8), GmshCellEntry(124, PYR, 3, 9), 160066ea43fSLisandro Dalcin GmshCellEntry(-1, PYR, 3, 10) 1610598e1a2SLisandro Dalcin 1620598e1a2SLisandro Dalcin #if 0 163066ea43fSLisandro Dalcin {20, GMSH_TRI, 2, 3, 3, 9, NULL}, 164066ea43fSLisandro Dalcin {18, GMSH_PRI, 3, 2, 6, 15, NULL}, 165066ea43fSLisandro Dalcin {19, GMSH_PYR, 3, 2, 5, 13, NULL}, 1660598e1a2SLisandro Dalcin #endif 1670598e1a2SLisandro Dalcin }; 1680598e1a2SLisandro Dalcin 1690598e1a2SLisandro Dalcin static GmshCellInfo GmshCellMap[150]; 1700598e1a2SLisandro Dalcin 171d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshCellInfoSetUp(void) 172d71ae5a4SJacob Faibussowitsch { 1730598e1a2SLisandro Dalcin size_t i, n; 1740598e1a2SLisandro Dalcin static PetscBool called = PETSC_FALSE; 1750598e1a2SLisandro Dalcin 1760598e1a2SLisandro Dalcin PetscFunctionBegin; 1774d86920dSPierre Jolivet if (called) PetscFunctionReturn(PETSC_SUCCESS); 1780598e1a2SLisandro Dalcin called = PETSC_TRUE; 179dd39110bSPierre Jolivet n = PETSC_STATIC_ARRAY_LENGTH(GmshCellMap); 1800598e1a2SLisandro Dalcin for (i = 0; i < n; ++i) { 1810598e1a2SLisandro Dalcin GmshCellMap[i].cellType = -1; 182066ea43fSLisandro Dalcin GmshCellMap[i].polytope = -1; 1830598e1a2SLisandro Dalcin } 184dd39110bSPierre Jolivet n = PETSC_STATIC_ARRAY_LENGTH(GmshCellTable); 185066ea43fSLisandro Dalcin for (i = 0; i < n; ++i) { 186066ea43fSLisandro Dalcin if (GmshCellTable[i].cellType <= 0) continue; 187066ea43fSLisandro Dalcin GmshCellMap[GmshCellTable[i].cellType] = GmshCellTable[i]; 188066ea43fSLisandro Dalcin } 1893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1900598e1a2SLisandro Dalcin } 1910598e1a2SLisandro Dalcin 1929371c9d4SSatish Balay #define GmshCellTypeCheck(ct) \ 1939371c9d4SSatish Balay PetscMacroReturnStandard(const int _ct_ = (int)ct; PetscCheck(_ct_ >= 0 && _ct_ < (int)PETSC_STATIC_ARRAY_LENGTH(GmshCellMap), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid Gmsh element type %d", _ct_); PetscCheck(GmshCellMap[_ct_].cellType == _ct_, PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported Gmsh element type %d", _ct_); \ 1949371c9d4SSatish Balay PetscCheck(GmshCellMap[_ct_].polytope != -1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported Gmsh element type %d", _ct_);) 1950598e1a2SLisandro Dalcin 1960598e1a2SLisandro Dalcin typedef struct { 197698a79b9SLisandro Dalcin PetscViewer viewer; 198698a79b9SLisandro Dalcin int fileFormat; 199698a79b9SLisandro Dalcin int dataSize; 200698a79b9SLisandro Dalcin PetscBool binary; 201698a79b9SLisandro Dalcin PetscBool byteSwap; 202698a79b9SLisandro Dalcin size_t wlen; 203698a79b9SLisandro Dalcin void *wbuf; 204698a79b9SLisandro Dalcin size_t slen; 205698a79b9SLisandro Dalcin void *sbuf; 2060598e1a2SLisandro Dalcin PetscInt *nbuf; 2070598e1a2SLisandro Dalcin PetscInt nodeStart; 2080598e1a2SLisandro Dalcin PetscInt nodeEnd; 20933a088b6SMatthew G. Knepley PetscInt *nodeMap; 210698a79b9SLisandro Dalcin } GmshFile; 211de78e4feSLisandro Dalcin 212d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshBufferGet(GmshFile *gmsh, size_t count, size_t eltsize, void *buf) 213d71ae5a4SJacob Faibussowitsch { 214de78e4feSLisandro Dalcin size_t size = count * eltsize; 21511c56cb0SLisandro Dalcin 21611c56cb0SLisandro Dalcin PetscFunctionBegin; 217698a79b9SLisandro Dalcin if (gmsh->wlen < size) { 2189566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->wbuf)); 2199566063dSJacob Faibussowitsch PetscCall(PetscMalloc(size, &gmsh->wbuf)); 220698a79b9SLisandro Dalcin gmsh->wlen = size; 221de78e4feSLisandro Dalcin } 222698a79b9SLisandro Dalcin *(void **)buf = size ? gmsh->wbuf : NULL; 2233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 224de78e4feSLisandro Dalcin } 225de78e4feSLisandro Dalcin 226d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshBufferSizeGet(GmshFile *gmsh, size_t count, void *buf) 227d71ae5a4SJacob Faibussowitsch { 228698a79b9SLisandro Dalcin size_t dataSize = (size_t)gmsh->dataSize; 229698a79b9SLisandro Dalcin size_t size = count * dataSize; 230698a79b9SLisandro Dalcin 231698a79b9SLisandro Dalcin PetscFunctionBegin; 232698a79b9SLisandro Dalcin if (gmsh->slen < size) { 2339566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->sbuf)); 2349566063dSJacob Faibussowitsch PetscCall(PetscMalloc(size, &gmsh->sbuf)); 235698a79b9SLisandro Dalcin gmsh->slen = size; 236698a79b9SLisandro Dalcin } 237698a79b9SLisandro Dalcin *(void **)buf = size ? gmsh->sbuf : NULL; 2383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 239698a79b9SLisandro Dalcin } 240698a79b9SLisandro Dalcin 241d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshRead(GmshFile *gmsh, void *buf, PetscInt count, PetscDataType dtype) 242d71ae5a4SJacob Faibussowitsch { 243de78e4feSLisandro Dalcin PetscFunctionBegin; 2449566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(gmsh->viewer, buf, count, NULL, dtype)); 2459566063dSJacob Faibussowitsch if (gmsh->byteSwap) PetscCall(PetscByteSwap(buf, dtype, count)); 2463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 247698a79b9SLisandro Dalcin } 248698a79b9SLisandro Dalcin 249d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadString(GmshFile *gmsh, char *buf, PetscInt count) 250d71ae5a4SJacob Faibussowitsch { 251698a79b9SLisandro Dalcin PetscFunctionBegin; 2529566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(gmsh->viewer, buf, count, NULL, PETSC_STRING)); 2533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 254698a79b9SLisandro Dalcin } 255698a79b9SLisandro Dalcin 256d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshMatch(PETSC_UNUSED GmshFile *gmsh, const char Section[], char line[PETSC_MAX_PATH_LEN], PetscBool *match) 257d71ae5a4SJacob Faibussowitsch { 258d6689ca9SLisandro Dalcin PetscFunctionBegin; 2599566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(line, Section, match)); 2603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 261d6689ca9SLisandro Dalcin } 262d6689ca9SLisandro Dalcin 263d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshExpect(GmshFile *gmsh, const char Section[], char line[PETSC_MAX_PATH_LEN]) 264d71ae5a4SJacob Faibussowitsch { 265d6689ca9SLisandro Dalcin PetscBool match; 266d6689ca9SLisandro Dalcin 267d6689ca9SLisandro Dalcin PetscFunctionBegin; 2689566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, Section, line, &match)); 26900045ab3SPierre Jolivet PetscCheck(match, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file, expecting %s, not %s", Section, line); 2703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 271d6689ca9SLisandro Dalcin } 272d6689ca9SLisandro Dalcin 273d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadSection(GmshFile *gmsh, char line[PETSC_MAX_PATH_LEN]) 274d71ae5a4SJacob Faibussowitsch { 275d6689ca9SLisandro Dalcin PetscBool match; 276d6689ca9SLisandro Dalcin 277d6689ca9SLisandro Dalcin PetscFunctionBegin; 278d6689ca9SLisandro Dalcin while (PETSC_TRUE) { 2799566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 1)); 2809566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, "$Comments", line, &match)); 281d6689ca9SLisandro Dalcin if (!match) break; 282d6689ca9SLisandro Dalcin while (PETSC_TRUE) { 2839566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 1)); 2849566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, "$EndComments", line, &match)); 285d6689ca9SLisandro Dalcin if (match) break; 286d6689ca9SLisandro Dalcin } 287d6689ca9SLisandro Dalcin } 2883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 289d6689ca9SLisandro Dalcin } 290d6689ca9SLisandro Dalcin 291d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEndSection(GmshFile *gmsh, const char EndSection[], char line[PETSC_MAX_PATH_LEN]) 292d71ae5a4SJacob Faibussowitsch { 293d6689ca9SLisandro Dalcin PetscFunctionBegin; 2949566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 1)); 2959566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, EndSection, line)); 2963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 297d6689ca9SLisandro Dalcin } 298d6689ca9SLisandro Dalcin 299d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadSize(GmshFile *gmsh, PetscInt *buf, PetscInt count) 300d71ae5a4SJacob Faibussowitsch { 301698a79b9SLisandro Dalcin PetscInt i; 302698a79b9SLisandro Dalcin size_t dataSize = (size_t)gmsh->dataSize; 303698a79b9SLisandro Dalcin 304698a79b9SLisandro Dalcin PetscFunctionBegin; 305698a79b9SLisandro Dalcin if (dataSize == sizeof(PetscInt)) { 3069566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, buf, count, PETSC_INT)); 307698a79b9SLisandro Dalcin } else if (dataSize == sizeof(int)) { 308698a79b9SLisandro Dalcin int *ibuf = NULL; 3099566063dSJacob Faibussowitsch PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf)); 3109566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, ibuf, count, PETSC_ENUM)); 311698a79b9SLisandro Dalcin for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i]; 312698a79b9SLisandro Dalcin } else if (dataSize == sizeof(long)) { 313698a79b9SLisandro Dalcin long *ibuf = NULL; 3149566063dSJacob Faibussowitsch PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf)); 3159566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, ibuf, count, PETSC_LONG)); 316698a79b9SLisandro Dalcin for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i]; 317698a79b9SLisandro Dalcin } else if (dataSize == sizeof(PetscInt64)) { 318698a79b9SLisandro Dalcin PetscInt64 *ibuf = NULL; 3199566063dSJacob Faibussowitsch PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf)); 3209566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, ibuf, count, PETSC_INT64)); 321698a79b9SLisandro Dalcin for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i]; 322698a79b9SLisandro Dalcin } 3233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 324698a79b9SLisandro Dalcin } 325698a79b9SLisandro Dalcin 326d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadInt(GmshFile *gmsh, int *buf, PetscInt count) 327d71ae5a4SJacob Faibussowitsch { 328698a79b9SLisandro Dalcin PetscFunctionBegin; 3299566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, buf, count, PETSC_ENUM)); 3303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 331698a79b9SLisandro Dalcin } 332698a79b9SLisandro Dalcin 333d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadDouble(GmshFile *gmsh, double *buf, PetscInt count) 334d71ae5a4SJacob Faibussowitsch { 335698a79b9SLisandro Dalcin PetscFunctionBegin; 3369566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, buf, count, PETSC_DOUBLE)); 3373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 338de78e4feSLisandro Dalcin } 339de78e4feSLisandro Dalcin 3409c0edc59SMatthew G. Knepley #define GMSH_MAX_TAGS 16 3417d5b9244SMatthew G. Knepley 342de78e4feSLisandro Dalcin typedef struct { 3430598e1a2SLisandro Dalcin PetscInt id; /* Entity ID */ 3440598e1a2SLisandro Dalcin PetscInt dim; /* Dimension */ 345de78e4feSLisandro Dalcin double bbox[6]; /* Bounding box */ 346de78e4feSLisandro Dalcin PetscInt numTags; /* Size of tag array */ 3477d5b9244SMatthew G. Knepley int tags[GMSH_MAX_TAGS]; /* Tag array */ 348de78e4feSLisandro Dalcin } GmshEntity; 349de78e4feSLisandro Dalcin 350de78e4feSLisandro Dalcin typedef struct { 351730356f6SLisandro Dalcin GmshEntity *entity[4]; 352730356f6SLisandro Dalcin PetscHMapI entityMap[4]; 353730356f6SLisandro Dalcin } GmshEntities; 354730356f6SLisandro Dalcin 355d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshEntitiesCreate(PetscInt count[4], GmshEntities **entities) 356d71ae5a4SJacob Faibussowitsch { 357730356f6SLisandro Dalcin PetscInt dim; 358730356f6SLisandro Dalcin 359730356f6SLisandro Dalcin PetscFunctionBegin; 3609566063dSJacob Faibussowitsch PetscCall(PetscNew(entities)); 361730356f6SLisandro Dalcin for (dim = 0; dim < 4; ++dim) { 3629566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(count[dim], &(*entities)->entity[dim])); 3639566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&(*entities)->entityMap[dim])); 364730356f6SLisandro Dalcin } 3653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 366730356f6SLisandro Dalcin } 367730356f6SLisandro Dalcin 368d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshEntitiesDestroy(GmshEntities **entities) 369d71ae5a4SJacob Faibussowitsch { 3700598e1a2SLisandro Dalcin PetscInt dim; 3710598e1a2SLisandro Dalcin 3720598e1a2SLisandro Dalcin PetscFunctionBegin; 3733ba16761SJacob Faibussowitsch if (!*entities) PetscFunctionReturn(PETSC_SUCCESS); 3740598e1a2SLisandro Dalcin for (dim = 0; dim < 4; ++dim) { 3759566063dSJacob Faibussowitsch PetscCall(PetscFree((*entities)->entity[dim])); 3769566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&(*entities)->entityMap[dim])); 3770598e1a2SLisandro Dalcin } 378f4f49eeaSPierre Jolivet PetscCall(PetscFree(*entities)); 3793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3800598e1a2SLisandro Dalcin } 3810598e1a2SLisandro Dalcin 382d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshEntitiesAdd(GmshEntities *entities, PetscInt index, PetscInt dim, PetscInt eid, GmshEntity **entity) 383d71ae5a4SJacob Faibussowitsch { 384730356f6SLisandro Dalcin PetscFunctionBegin; 3859566063dSJacob Faibussowitsch PetscCall(PetscHMapISet(entities->entityMap[dim], eid, index)); 386730356f6SLisandro Dalcin entities->entity[dim][index].dim = dim; 387730356f6SLisandro Dalcin entities->entity[dim][index].id = eid; 388730356f6SLisandro Dalcin if (entity) *entity = &entities->entity[dim][index]; 3893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 390730356f6SLisandro Dalcin } 391730356f6SLisandro Dalcin 392d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshEntitiesGet(GmshEntities *entities, PetscInt dim, PetscInt eid, GmshEntity **entity) 393d71ae5a4SJacob Faibussowitsch { 394730356f6SLisandro Dalcin PetscInt index; 395730356f6SLisandro Dalcin 396730356f6SLisandro Dalcin PetscFunctionBegin; 3979566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(entities->entityMap[dim], eid, &index)); 398730356f6SLisandro Dalcin *entity = &entities->entity[dim][index]; 3993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 400730356f6SLisandro Dalcin } 401730356f6SLisandro Dalcin 4020598e1a2SLisandro Dalcin typedef struct { 4030598e1a2SLisandro Dalcin PetscInt *id; /* Node IDs */ 4040598e1a2SLisandro Dalcin double *xyz; /* Coordinates */ 40581a1af93SMatthew G. Knepley PetscInt *tag; /* Physical tag */ 4060598e1a2SLisandro Dalcin } GmshNodes; 4070598e1a2SLisandro Dalcin 408d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshNodesCreate(PetscInt count, GmshNodes **nodes) 409d71ae5a4SJacob Faibussowitsch { 410730356f6SLisandro Dalcin PetscFunctionBegin; 4119566063dSJacob Faibussowitsch PetscCall(PetscNew(nodes)); 4129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(count * 1, &(*nodes)->id)); 4139566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(count * 3, &(*nodes)->xyz)); 4147d5b9244SMatthew G. Knepley PetscCall(PetscMalloc1(count * GMSH_MAX_TAGS, &(*nodes)->tag)); 4153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 416730356f6SLisandro Dalcin } 4170598e1a2SLisandro Dalcin 418d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshNodesDestroy(GmshNodes **nodes) 419d71ae5a4SJacob Faibussowitsch { 4200598e1a2SLisandro Dalcin PetscFunctionBegin; 4213ba16761SJacob Faibussowitsch if (!*nodes) PetscFunctionReturn(PETSC_SUCCESS); 4229566063dSJacob Faibussowitsch PetscCall(PetscFree((*nodes)->id)); 4239566063dSJacob Faibussowitsch PetscCall(PetscFree((*nodes)->xyz)); 4249566063dSJacob Faibussowitsch PetscCall(PetscFree((*nodes)->tag)); 425f4f49eeaSPierre Jolivet PetscCall(PetscFree(*nodes)); 4263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 427730356f6SLisandro Dalcin } 428730356f6SLisandro Dalcin 429730356f6SLisandro Dalcin typedef struct { 4300598e1a2SLisandro Dalcin PetscInt id; /* Element ID */ 4310598e1a2SLisandro Dalcin PetscInt dim; /* Dimension */ 432de78e4feSLisandro Dalcin PetscInt cellType; /* Cell type */ 4330598e1a2SLisandro Dalcin PetscInt numVerts; /* Size of vertex array */ 434de78e4feSLisandro Dalcin PetscInt numNodes; /* Size of node array */ 4350598e1a2SLisandro Dalcin PetscInt *nodes; /* Vertex/Node array */ 43681a1af93SMatthew G. Knepley PetscInt numTags; /* Size of physical tag array */ 4377d5b9244SMatthew G. Knepley int tags[GMSH_MAX_TAGS]; /* Physical tag array */ 438de78e4feSLisandro Dalcin } GmshElement; 439de78e4feSLisandro Dalcin 440d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshElementsCreate(PetscInt count, GmshElement **elements) 441d71ae5a4SJacob Faibussowitsch { 4420598e1a2SLisandro Dalcin PetscFunctionBegin; 4439566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(count, elements)); 4443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4450598e1a2SLisandro Dalcin } 4460598e1a2SLisandro Dalcin 447d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshElementsDestroy(GmshElement **elements) 448d71ae5a4SJacob Faibussowitsch { 4490598e1a2SLisandro Dalcin PetscFunctionBegin; 4503ba16761SJacob Faibussowitsch if (!*elements) PetscFunctionReturn(PETSC_SUCCESS); 4519566063dSJacob Faibussowitsch PetscCall(PetscFree(*elements)); 4523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4530598e1a2SLisandro Dalcin } 4540598e1a2SLisandro Dalcin 4550598e1a2SLisandro Dalcin typedef struct { 4560598e1a2SLisandro Dalcin PetscInt dim; 457066ea43fSLisandro Dalcin PetscInt order; 4580598e1a2SLisandro Dalcin GmshEntities *entities; 4590598e1a2SLisandro Dalcin PetscInt numNodes; 4600598e1a2SLisandro Dalcin GmshNodes *nodelist; 4610598e1a2SLisandro Dalcin PetscInt numElems; 4620598e1a2SLisandro Dalcin GmshElement *elements; 4630598e1a2SLisandro Dalcin PetscInt numVerts; 4640598e1a2SLisandro Dalcin PetscInt numCells; 4650598e1a2SLisandro Dalcin PetscInt *periodMap; 4660598e1a2SLisandro Dalcin PetscInt *vertexMap; 4670598e1a2SLisandro Dalcin PetscSegBuffer segbuf; 468a45dabc8SMatthew G. Knepley PetscInt numRegions; 46990d778b8SLisandro Dalcin PetscInt *regionDims; 470a45dabc8SMatthew G. Knepley PetscInt *regionTags; 471a45dabc8SMatthew G. Knepley char **regionNames; 4720598e1a2SLisandro Dalcin } GmshMesh; 4730598e1a2SLisandro Dalcin 474d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshMeshCreate(GmshMesh **mesh) 475d71ae5a4SJacob Faibussowitsch { 4760598e1a2SLisandro Dalcin PetscFunctionBegin; 4779566063dSJacob Faibussowitsch PetscCall(PetscNew(mesh)); 4789566063dSJacob Faibussowitsch PetscCall(PetscSegBufferCreate(sizeof(PetscInt), 0, &(*mesh)->segbuf)); 4793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4800598e1a2SLisandro Dalcin } 4810598e1a2SLisandro Dalcin 482d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshMeshDestroy(GmshMesh **mesh) 483d71ae5a4SJacob Faibussowitsch { 484a45dabc8SMatthew G. Knepley PetscInt r; 4850598e1a2SLisandro Dalcin 4860598e1a2SLisandro Dalcin PetscFunctionBegin; 4873ba16761SJacob Faibussowitsch if (!*mesh) PetscFunctionReturn(PETSC_SUCCESS); 4889566063dSJacob Faibussowitsch PetscCall(GmshEntitiesDestroy(&(*mesh)->entities)); 4899566063dSJacob Faibussowitsch PetscCall(GmshNodesDestroy(&(*mesh)->nodelist)); 4909566063dSJacob Faibussowitsch PetscCall(GmshElementsDestroy(&(*mesh)->elements)); 4919566063dSJacob Faibussowitsch PetscCall(PetscFree((*mesh)->periodMap)); 4929566063dSJacob Faibussowitsch PetscCall(PetscFree((*mesh)->vertexMap)); 4939566063dSJacob Faibussowitsch PetscCall(PetscSegBufferDestroy(&(*mesh)->segbuf)); 4949566063dSJacob Faibussowitsch for (r = 0; r < (*mesh)->numRegions; ++r) PetscCall(PetscFree((*mesh)->regionNames[r])); 49590d778b8SLisandro Dalcin PetscCall(PetscFree3((*mesh)->regionDims, (*mesh)->regionTags, (*mesh)->regionNames)); 496f4f49eeaSPierre Jolivet PetscCall(PetscFree(*mesh)); 4973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4980598e1a2SLisandro Dalcin } 4990598e1a2SLisandro Dalcin 500d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes_v22(GmshFile *gmsh, GmshMesh *mesh) 501d71ae5a4SJacob Faibussowitsch { 502698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 503698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 504de78e4feSLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 5057d5b9244SMatthew G. Knepley int n, t, num, nid, snum; 5060598e1a2SLisandro Dalcin GmshNodes *nodes; 507de78e4feSLisandro Dalcin 508de78e4feSLisandro Dalcin PetscFunctionBegin; 5099566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 510698a79b9SLisandro Dalcin snum = sscanf(line, "%d", &num); 51108401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 5129566063dSJacob Faibussowitsch PetscCall(GmshNodesCreate(num, &nodes)); 5130598e1a2SLisandro Dalcin mesh->numNodes = num; 5140598e1a2SLisandro Dalcin mesh->nodelist = nodes; 5150598e1a2SLisandro Dalcin for (n = 0; n < num; ++n) { 5160598e1a2SLisandro Dalcin double *xyz = nodes->xyz + n * 3; 5179566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM)); 5189566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE)); 5199566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nid, PETSC_ENUM, 1)); 5209566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(xyz, PETSC_DOUBLE, 3)); 5210598e1a2SLisandro Dalcin nodes->id[n] = nid; 5227d5b9244SMatthew G. Knepley for (t = 0; t < GMSH_MAX_TAGS; ++t) nodes->tag[n * GMSH_MAX_TAGS + t] = -1; 52311c56cb0SLisandro Dalcin } 5243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 52511c56cb0SLisandro Dalcin } 52611c56cb0SLisandro Dalcin 527de78e4feSLisandro Dalcin /* Gmsh elements can be of any dimension/co-dimension, so we need to traverse the 528de78e4feSLisandro Dalcin file contents multiple times to figure out the true number of cells and facets 529de78e4feSLisandro Dalcin in the given mesh. To make this more efficient we read the file contents only 530de78e4feSLisandro Dalcin once and store them in memory, while determining the true number of cells. */ 531d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements_v22(GmshFile *gmsh, GmshMesh *mesh) 532d71ae5a4SJacob Faibussowitsch { 533698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 534698a79b9SLisandro Dalcin PetscBool binary = gmsh->binary; 535698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 536de78e4feSLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 5370598e1a2SLisandro Dalcin int i, c, p, num, ibuf[1 + 4 + 1000], snum; 5380598e1a2SLisandro Dalcin int cellType, numElem, numVerts, numNodes, numTags; 539df032b82SMatthew G. Knepley GmshElement *elements; 5400598e1a2SLisandro Dalcin PetscInt *nodeMap = gmsh->nodeMap; 541df032b82SMatthew G. Knepley 542df032b82SMatthew G. Knepley PetscFunctionBegin; 5439566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 544698a79b9SLisandro Dalcin snum = sscanf(line, "%d", &num); 54508401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 5469566063dSJacob Faibussowitsch PetscCall(GmshElementsCreate(num, &elements)); 5470598e1a2SLisandro Dalcin mesh->numElems = num; 5480598e1a2SLisandro Dalcin mesh->elements = elements; 549698a79b9SLisandro Dalcin for (c = 0; c < num;) { 5509566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM)); 5519566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, 3)); 5520598e1a2SLisandro Dalcin 5530598e1a2SLisandro Dalcin cellType = binary ? ibuf[0] : ibuf[1]; 5540598e1a2SLisandro Dalcin numElem = binary ? ibuf[1] : 1; 555df032b82SMatthew G. Knepley numTags = ibuf[2]; 5560598e1a2SLisandro Dalcin 5579566063dSJacob Faibussowitsch PetscCall(GmshCellTypeCheck(cellType)); 5580598e1a2SLisandro Dalcin numVerts = GmshCellMap[cellType].numVerts; 5590598e1a2SLisandro Dalcin numNodes = GmshCellMap[cellType].numNodes; 5600598e1a2SLisandro Dalcin 561df032b82SMatthew G. Knepley for (i = 0; i < numElem; ++i, ++c) { 5620598e1a2SLisandro Dalcin GmshElement *element = elements + c; 5630598e1a2SLisandro Dalcin const int off = binary ? 0 : 1, nint = 1 + numTags + numNodes - off; 5640598e1a2SLisandro Dalcin const int *id = ibuf, *nodes = ibuf + 1 + numTags, *tags = ibuf + 1; 5659566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf + off, nint, NULL, PETSC_ENUM)); 5669566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf + off, PETSC_ENUM, nint)); 5670598e1a2SLisandro Dalcin element->id = id[0]; 5680598e1a2SLisandro Dalcin element->dim = GmshCellMap[cellType].dim; 5690598e1a2SLisandro Dalcin element->cellType = cellType; 5700598e1a2SLisandro Dalcin element->numVerts = numVerts; 5710598e1a2SLisandro Dalcin element->numNodes = numNodes; 5727d5b9244SMatthew G. Knepley element->numTags = PetscMin(numTags, GMSH_MAX_TAGS); 5739566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes)); 5740598e1a2SLisandro Dalcin for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]]; 5750598e1a2SLisandro Dalcin for (p = 0; p < element->numTags; p++) element->tags[p] = tags[p]; 576df032b82SMatthew G. Knepley } 577df032b82SMatthew G. Knepley } 5783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 579df032b82SMatthew G. Knepley } 5807d282ae0SMichael Lange 581de78e4feSLisandro Dalcin /* 582de78e4feSLisandro Dalcin $Entities 583de78e4feSLisandro Dalcin numPoints(unsigned long) numCurves(unsigned long) 584de78e4feSLisandro Dalcin numSurfaces(unsigned long) numVolumes(unsigned long) 585de78e4feSLisandro Dalcin // points 586de78e4feSLisandro Dalcin tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 587de78e4feSLisandro Dalcin boxMaxX(double) boxMaxY(double) boxMaxZ(double) 588de78e4feSLisandro Dalcin numPhysicals(unsigned long) phyisicalTag[...](int) 589de78e4feSLisandro Dalcin ... 590de78e4feSLisandro Dalcin // curves 591de78e4feSLisandro Dalcin tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 592de78e4feSLisandro Dalcin boxMaxX(double) boxMaxY(double) boxMaxZ(double) 593de78e4feSLisandro Dalcin numPhysicals(unsigned long) physicalTag[...](int) 594de78e4feSLisandro Dalcin numBREPVert(unsigned long) tagBREPVert[...](int) 595de78e4feSLisandro Dalcin ... 596de78e4feSLisandro Dalcin // surfaces 597de78e4feSLisandro Dalcin tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 598de78e4feSLisandro Dalcin boxMaxX(double) boxMaxY(double) boxMaxZ(double) 599de78e4feSLisandro Dalcin numPhysicals(unsigned long) physicalTag[...](int) 600de78e4feSLisandro Dalcin numBREPCurve(unsigned long) tagBREPCurve[...](int) 601de78e4feSLisandro Dalcin ... 602de78e4feSLisandro Dalcin // volumes 603de78e4feSLisandro Dalcin tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 604de78e4feSLisandro Dalcin boxMaxX(double) boxMaxY(double) boxMaxZ(double) 605de78e4feSLisandro Dalcin numPhysicals(unsigned long) physicalTag[...](int) 606de78e4feSLisandro Dalcin numBREPSurfaces(unsigned long) tagBREPSurfaces[...](int) 607de78e4feSLisandro Dalcin ... 608de78e4feSLisandro Dalcin $EndEntities 609de78e4feSLisandro Dalcin */ 610d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEntities_v40(GmshFile *gmsh, GmshMesh *mesh) 611d71ae5a4SJacob Faibussowitsch { 612698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 613698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 614698a79b9SLisandro Dalcin long index, num, lbuf[4]; 615730356f6SLisandro Dalcin int dim, eid, numTags, *ibuf, t; 616698a79b9SLisandro Dalcin PetscInt count[4], i; 617a5ba3d71SLisandro Dalcin GmshEntity *entity = NULL; 618de78e4feSLisandro Dalcin 619de78e4feSLisandro Dalcin PetscFunctionBegin; 6209566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, lbuf, 4, NULL, PETSC_LONG)); 6219566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(lbuf, PETSC_LONG, 4)); 622698a79b9SLisandro Dalcin for (i = 0; i < 4; ++i) count[i] = lbuf[i]; 6239566063dSJacob Faibussowitsch PetscCall(GmshEntitiesCreate(count, &mesh->entities)); 624de78e4feSLisandro Dalcin for (dim = 0; dim < 4; ++dim) { 625730356f6SLisandro Dalcin for (index = 0; index < count[dim]; ++index) { 6269566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &eid, 1, NULL, PETSC_ENUM)); 6279566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&eid, PETSC_ENUM, 1)); 6289566063dSJacob Faibussowitsch PetscCall(GmshEntitiesAdd(mesh->entities, (PetscInt)index, dim, eid, &entity)); 6299566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, entity->bbox, 6, NULL, PETSC_DOUBLE)); 6309566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(entity->bbox, PETSC_DOUBLE, 6)); 6319566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &num, 1, NULL, PETSC_LONG)); 6329566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&num, PETSC_LONG, 1)); 6339566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, num, sizeof(int), &ibuf)); 6349566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, num, NULL, PETSC_ENUM)); 6359566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, num)); 6367d5b9244SMatthew G. Knepley entity->numTags = numTags = (int)PetscMin(num, GMSH_MAX_TAGS); 637de78e4feSLisandro Dalcin for (t = 0; t < numTags; ++t) entity->tags[t] = ibuf[t]; 638de78e4feSLisandro Dalcin if (dim == 0) continue; 6399566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &num, 1, NULL, PETSC_LONG)); 6409566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&num, PETSC_LONG, 1)); 6419566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, num, sizeof(int), &ibuf)); 6429566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, num, NULL, PETSC_ENUM)); 6439566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, num)); 644de78e4feSLisandro Dalcin } 645de78e4feSLisandro Dalcin } 6463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 647de78e4feSLisandro Dalcin } 648de78e4feSLisandro Dalcin 649de78e4feSLisandro Dalcin /* 650de78e4feSLisandro Dalcin $Nodes 651de78e4feSLisandro Dalcin numEntityBlocks(unsigned long) numNodes(unsigned long) 652de78e4feSLisandro Dalcin tagEntity(int) dimEntity(int) typeNode(int) numNodes(unsigned long) 653de78e4feSLisandro Dalcin tag(int) x(double) y(double) z(double) 654de78e4feSLisandro Dalcin ... 655de78e4feSLisandro Dalcin ... 656de78e4feSLisandro Dalcin $EndNodes 657de78e4feSLisandro Dalcin */ 658d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes_v40(GmshFile *gmsh, GmshMesh *mesh) 659d71ae5a4SJacob Faibussowitsch { 660698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 661698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 6627d5b9244SMatthew G. Knepley long block, node, n, t, numEntityBlocks, numTotalNodes, numNodes; 663de78e4feSLisandro Dalcin int info[3], nid; 6640598e1a2SLisandro Dalcin GmshNodes *nodes; 665de78e4feSLisandro Dalcin 666de78e4feSLisandro Dalcin PetscFunctionBegin; 6679566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numEntityBlocks, 1, NULL, PETSC_LONG)); 6689566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numEntityBlocks, PETSC_LONG, 1)); 6699566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numTotalNodes, 1, NULL, PETSC_LONG)); 6709566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numTotalNodes, PETSC_LONG, 1)); 6719566063dSJacob Faibussowitsch PetscCall(GmshNodesCreate(numTotalNodes, &nodes)); 6720598e1a2SLisandro Dalcin mesh->numNodes = numTotalNodes; 6730598e1a2SLisandro Dalcin mesh->nodelist = nodes; 6740598e1a2SLisandro Dalcin for (n = 0, block = 0; block < numEntityBlocks; ++block) { 6759566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, info, 3, NULL, PETSC_ENUM)); 6769566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numNodes, 1, NULL, PETSC_LONG)); 6779566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numNodes, PETSC_LONG, 1)); 678698a79b9SLisandro Dalcin if (gmsh->binary) { 679277f51e8SBarry Smith size_t nbytes = sizeof(int) + 3 * sizeof(double); 680da81f932SPierre Jolivet char *cbuf = NULL; /* dummy value to prevent warning from compiler about possible uninitialized value */ 6819566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, numNodes, nbytes, &cbuf)); 6829566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, cbuf, numNodes * nbytes, NULL, PETSC_CHAR)); 6830598e1a2SLisandro Dalcin for (node = 0; node < numNodes; ++node, ++n) { 684de78e4feSLisandro Dalcin char *cnid = cbuf + node * nbytes, *cxyz = cnid + sizeof(int); 6850598e1a2SLisandro Dalcin double *xyz = nodes->xyz + n * 3; 6869566063dSJacob Faibussowitsch if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(cnid, PETSC_ENUM, 1)); 6879566063dSJacob Faibussowitsch if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(cxyz, PETSC_DOUBLE, 3)); 6889566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(&nid, cnid, sizeof(int))); 6899566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(xyz, cxyz, 3 * sizeof(double))); 6909566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nid, PETSC_ENUM, 1)); 6919566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(xyz, PETSC_DOUBLE, 3)); 6920598e1a2SLisandro Dalcin nodes->id[n] = nid; 6937d5b9244SMatthew G. Knepley for (t = 0; t < GMSH_MAX_TAGS; ++t) nodes->tag[n * GMSH_MAX_TAGS + t] = -1; 694de78e4feSLisandro Dalcin } 695de78e4feSLisandro Dalcin } else { 6960598e1a2SLisandro Dalcin for (node = 0; node < numNodes; ++node, ++n) { 6970598e1a2SLisandro Dalcin double *xyz = nodes->xyz + n * 3; 6989566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM)); 6999566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE)); 7009566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nid, PETSC_ENUM, 1)); 7019566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(xyz, PETSC_DOUBLE, 3)); 7020598e1a2SLisandro Dalcin nodes->id[n] = nid; 7037d5b9244SMatthew G. Knepley for (t = 0; t < GMSH_MAX_TAGS; ++t) nodes->tag[n * GMSH_MAX_TAGS + t] = -1; 704de78e4feSLisandro Dalcin } 705de78e4feSLisandro Dalcin } 706de78e4feSLisandro Dalcin } 7073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 708de78e4feSLisandro Dalcin } 709de78e4feSLisandro Dalcin 710de78e4feSLisandro Dalcin /* 711de78e4feSLisandro Dalcin $Elements 712de78e4feSLisandro Dalcin numEntityBlocks(unsigned long) numElements(unsigned long) 713de78e4feSLisandro Dalcin tagEntity(int) dimEntity(int) typeEle(int) numElements(unsigned long) 714de78e4feSLisandro Dalcin tag(int) numVert[...](int) 715de78e4feSLisandro Dalcin ... 716de78e4feSLisandro Dalcin ... 717de78e4feSLisandro Dalcin $EndElements 718de78e4feSLisandro Dalcin */ 719d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements_v40(GmshFile *gmsh, GmshMesh *mesh) 720d71ae5a4SJacob Faibussowitsch { 721698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 722698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 723de78e4feSLisandro Dalcin long c, block, numEntityBlocks, numTotalElements, elem, numElements; 724de78e4feSLisandro Dalcin int p, info[3], *ibuf = NULL; 7250598e1a2SLisandro Dalcin int eid, dim, cellType, numVerts, numNodes, numTags; 726a5ba3d71SLisandro Dalcin GmshEntity *entity = NULL; 727de78e4feSLisandro Dalcin GmshElement *elements; 7280598e1a2SLisandro Dalcin PetscInt *nodeMap = gmsh->nodeMap; 729de78e4feSLisandro Dalcin 730de78e4feSLisandro Dalcin PetscFunctionBegin; 7319566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numEntityBlocks, 1, NULL, PETSC_LONG)); 7329566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numEntityBlocks, PETSC_LONG, 1)); 7339566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numTotalElements, 1, NULL, PETSC_LONG)); 7349566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numTotalElements, PETSC_LONG, 1)); 7359566063dSJacob Faibussowitsch PetscCall(GmshElementsCreate(numTotalElements, &elements)); 7360598e1a2SLisandro Dalcin mesh->numElems = numTotalElements; 7370598e1a2SLisandro Dalcin mesh->elements = elements; 738de78e4feSLisandro Dalcin for (c = 0, block = 0; block < numEntityBlocks; ++block) { 7399566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, info, 3, NULL, PETSC_ENUM)); 7409566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(info, PETSC_ENUM, 3)); 7419371c9d4SSatish Balay eid = info[0]; 7429371c9d4SSatish Balay dim = info[1]; 7439371c9d4SSatish Balay cellType = info[2]; 7449566063dSJacob Faibussowitsch PetscCall(GmshEntitiesGet(mesh->entities, dim, eid, &entity)); 7459566063dSJacob Faibussowitsch PetscCall(GmshCellTypeCheck(cellType)); 7460598e1a2SLisandro Dalcin numVerts = GmshCellMap[cellType].numVerts; 7470598e1a2SLisandro Dalcin numNodes = GmshCellMap[cellType].numNodes; 748730356f6SLisandro Dalcin numTags = entity->numTags; 7499566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numElements, 1, NULL, PETSC_LONG)); 7509566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numElements, PETSC_LONG, 1)); 7519566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, (1 + numNodes) * numElements, sizeof(int), &ibuf)); 7529566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, (1 + numNodes) * numElements, NULL, PETSC_ENUM)); 7539566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, (1 + numNodes) * numElements)); 754de78e4feSLisandro Dalcin for (elem = 0; elem < numElements; ++elem, ++c) { 755de78e4feSLisandro Dalcin GmshElement *element = elements + c; 7560598e1a2SLisandro Dalcin const int *id = ibuf + elem * (1 + numNodes), *nodes = id + 1; 7570598e1a2SLisandro Dalcin element->id = id[0]; 758de78e4feSLisandro Dalcin element->dim = dim; 759de78e4feSLisandro Dalcin element->cellType = cellType; 7600598e1a2SLisandro Dalcin element->numVerts = numVerts; 761de78e4feSLisandro Dalcin element->numNodes = numNodes; 762de78e4feSLisandro Dalcin element->numTags = numTags; 7639566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes)); 7640598e1a2SLisandro Dalcin for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]]; 7650598e1a2SLisandro Dalcin for (p = 0; p < element->numTags; p++) element->tags[p] = entity->tags[p]; 766de78e4feSLisandro Dalcin } 767de78e4feSLisandro Dalcin } 7683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 769698a79b9SLisandro Dalcin } 770698a79b9SLisandro Dalcin 771d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPeriodic_v40(GmshFile *gmsh, PetscInt periodicMap[]) 772d71ae5a4SJacob Faibussowitsch { 773698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 774698a79b9SLisandro Dalcin int fileFormat = gmsh->fileFormat; 775698a79b9SLisandro Dalcin PetscBool binary = gmsh->binary; 776698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 777698a79b9SLisandro Dalcin int numPeriodic, snum, i; 778698a79b9SLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 7790598e1a2SLisandro Dalcin PetscInt *nodeMap = gmsh->nodeMap; 780698a79b9SLisandro Dalcin 781698a79b9SLisandro Dalcin PetscFunctionBegin; 782698a79b9SLisandro Dalcin if (fileFormat == 22 || !binary) { 7839566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 784698a79b9SLisandro Dalcin snum = sscanf(line, "%d", &numPeriodic); 78508401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 786698a79b9SLisandro Dalcin } else { 7879566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numPeriodic, 1, NULL, PETSC_ENUM)); 7889566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numPeriodic, PETSC_ENUM, 1)); 789698a79b9SLisandro Dalcin } 790698a79b9SLisandro Dalcin for (i = 0; i < numPeriodic; i++) { 7919dddd249SSatish Balay int ibuf[3], correspondingDim = -1, correspondingTag = -1, primaryTag = -1, correspondingNode, primaryNode; 792698a79b9SLisandro Dalcin long j, nNodes; 793698a79b9SLisandro Dalcin double affine[16]; 794698a79b9SLisandro Dalcin 795698a79b9SLisandro Dalcin if (fileFormat == 22 || !binary) { 7969566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 3, NULL, PETSC_STRING)); 7979dddd249SSatish Balay snum = sscanf(line, "%d %d %d", &correspondingDim, &correspondingTag, &primaryTag); 79808401ef6SPierre Jolivet PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 799698a79b9SLisandro Dalcin } else { 8009566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM)); 8019566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, 3)); 8029371c9d4SSatish Balay correspondingDim = ibuf[0]; 8039371c9d4SSatish Balay correspondingTag = ibuf[1]; 8049371c9d4SSatish Balay primaryTag = ibuf[2]; 805698a79b9SLisandro Dalcin } 8069371c9d4SSatish Balay (void)correspondingDim; 8079371c9d4SSatish Balay (void)correspondingTag; 8089371c9d4SSatish Balay (void)primaryTag; /* unused */ 809698a79b9SLisandro Dalcin 810698a79b9SLisandro Dalcin if (fileFormat == 22 || !binary) { 8119566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 812698a79b9SLisandro Dalcin snum = sscanf(line, "%ld", &nNodes); 8134c500f23SPierre Jolivet if (snum != 1) { /* discard transformation and try again */ 8149566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, -PETSC_MAX_PATH_LEN, NULL, PETSC_STRING)); 8159566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 816698a79b9SLisandro Dalcin snum = sscanf(line, "%ld", &nNodes); 81708401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 818698a79b9SLisandro Dalcin } 819698a79b9SLisandro Dalcin } else { 8209566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &nNodes, 1, NULL, PETSC_LONG)); 8219566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nNodes, PETSC_LONG, 1)); 8224c500f23SPierre Jolivet if (nNodes == -1) { /* discard transformation and try again */ 8239566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, affine, 16, NULL, PETSC_DOUBLE)); 8249566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &nNodes, 1, NULL, PETSC_LONG)); 8259566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nNodes, PETSC_LONG, 1)); 826698a79b9SLisandro Dalcin } 827698a79b9SLisandro Dalcin } 828698a79b9SLisandro Dalcin 829698a79b9SLisandro Dalcin for (j = 0; j < nNodes; j++) { 830698a79b9SLisandro Dalcin if (fileFormat == 22 || !binary) { 8319566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 2, NULL, PETSC_STRING)); 8329dddd249SSatish Balay snum = sscanf(line, "%d %d", &correspondingNode, &primaryNode); 83308401ef6SPierre Jolivet PetscCheck(snum == 2, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 834698a79b9SLisandro Dalcin } else { 8359566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, 2, NULL, PETSC_ENUM)); 8369566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, 2)); 8379371c9d4SSatish Balay correspondingNode = ibuf[0]; 8389371c9d4SSatish Balay primaryNode = ibuf[1]; 839698a79b9SLisandro Dalcin } 8409dddd249SSatish Balay correspondingNode = (int)nodeMap[correspondingNode]; 8419dddd249SSatish Balay primaryNode = (int)nodeMap[primaryNode]; 8429dddd249SSatish Balay periodicMap[correspondingNode] = primaryNode; 843698a79b9SLisandro Dalcin } 844698a79b9SLisandro Dalcin } 8453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 846698a79b9SLisandro Dalcin } 847698a79b9SLisandro Dalcin 8480598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 849698a79b9SLisandro Dalcin $Entities 850698a79b9SLisandro Dalcin numPoints(size_t) numCurves(size_t) 851698a79b9SLisandro Dalcin numSurfaces(size_t) numVolumes(size_t) 852698a79b9SLisandro Dalcin pointTag(int) X(double) Y(double) Z(double) 853698a79b9SLisandro Dalcin numPhysicalTags(size_t) physicalTag(int) ... 854698a79b9SLisandro Dalcin ... 855698a79b9SLisandro Dalcin curveTag(int) minX(double) minY(double) minZ(double) 856698a79b9SLisandro Dalcin maxX(double) maxY(double) maxZ(double) 857698a79b9SLisandro Dalcin numPhysicalTags(size_t) physicalTag(int) ... 858698a79b9SLisandro Dalcin numBoundingPoints(size_t) pointTag(int) ... 859698a79b9SLisandro Dalcin ... 860698a79b9SLisandro Dalcin surfaceTag(int) minX(double) minY(double) minZ(double) 861698a79b9SLisandro Dalcin maxX(double) maxY(double) maxZ(double) 862698a79b9SLisandro Dalcin numPhysicalTags(size_t) physicalTag(int) ... 863698a79b9SLisandro Dalcin numBoundingCurves(size_t) curveTag(int) ... 864698a79b9SLisandro Dalcin ... 865698a79b9SLisandro Dalcin volumeTag(int) minX(double) minY(double) minZ(double) 866698a79b9SLisandro Dalcin maxX(double) maxY(double) maxZ(double) 867698a79b9SLisandro Dalcin numPhysicalTags(size_t) physicalTag(int) ... 868698a79b9SLisandro Dalcin numBoundngSurfaces(size_t) surfaceTag(int) ... 869698a79b9SLisandro Dalcin ... 870698a79b9SLisandro Dalcin $EndEntities 871698a79b9SLisandro Dalcin */ 872d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEntities_v41(GmshFile *gmsh, GmshMesh *mesh) 873d71ae5a4SJacob Faibussowitsch { 874698a79b9SLisandro Dalcin PetscInt count[4], index, numTags, i; 875698a79b9SLisandro Dalcin int dim, eid, *tags = NULL; 876698a79b9SLisandro Dalcin GmshEntity *entity = NULL; 877698a79b9SLisandro Dalcin 878698a79b9SLisandro Dalcin PetscFunctionBegin; 8799566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, count, 4)); 8809566063dSJacob Faibussowitsch PetscCall(GmshEntitiesCreate(count, &mesh->entities)); 881698a79b9SLisandro Dalcin for (dim = 0; dim < 4; ++dim) { 882698a79b9SLisandro Dalcin for (index = 0; index < count[dim]; ++index) { 8839566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, &eid, 1)); 8849566063dSJacob Faibussowitsch PetscCall(GmshEntitiesAdd(mesh->entities, (PetscInt)index, dim, eid, &entity)); 8859566063dSJacob Faibussowitsch PetscCall(GmshReadDouble(gmsh, entity->bbox, (dim == 0) ? 3 : 6)); 8869566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, &numTags, 1)); 8879566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, numTags, sizeof(int), &tags)); 8889566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, tags, numTags)); 8899c0edc59SMatthew G. Knepley PetscCheck(numTags <= GMSH_MAX_TAGS, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PETSc currently supports up to %" PetscInt_FMT " tags per entity, not %" PetscInt_FMT, (PetscInt)GMSH_MAX_TAGS, numTags); 8907d5b9244SMatthew G. Knepley entity->numTags = numTags; 891698a79b9SLisandro Dalcin for (i = 0; i < entity->numTags; ++i) entity->tags[i] = tags[i]; 892698a79b9SLisandro Dalcin if (dim == 0) continue; 8939566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, &numTags, 1)); 8949566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, numTags, sizeof(int), &tags)); 8959566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, tags, numTags)); 89681a1af93SMatthew G. Knepley /* Currently, we do not save the ids for the bounding entities */ 897698a79b9SLisandro Dalcin } 898698a79b9SLisandro Dalcin } 8993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 900698a79b9SLisandro Dalcin } 901698a79b9SLisandro Dalcin 90233a088b6SMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 903698a79b9SLisandro Dalcin $Nodes 904698a79b9SLisandro Dalcin numEntityBlocks(size_t) numNodes(size_t) 905698a79b9SLisandro Dalcin minNodeTag(size_t) maxNodeTag(size_t) 906698a79b9SLisandro Dalcin entityDim(int) entityTag(int) parametric(int; 0 or 1) numNodesBlock(size_t) 907698a79b9SLisandro Dalcin nodeTag(size_t) 908698a79b9SLisandro Dalcin ... 909698a79b9SLisandro Dalcin x(double) y(double) z(double) 910698a79b9SLisandro Dalcin < u(double; if parametric and entityDim = 1 or entityDim = 2) > 911698a79b9SLisandro Dalcin < v(double; if parametric and entityDim = 2) > 912698a79b9SLisandro Dalcin ... 913698a79b9SLisandro Dalcin ... 914698a79b9SLisandro Dalcin $EndNodes 915698a79b9SLisandro Dalcin */ 916d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes_v41(GmshFile *gmsh, GmshMesh *mesh) 917d71ae5a4SJacob Faibussowitsch { 91881a1af93SMatthew G. Knepley int info[3], dim, eid, parametric; 9197d5b9244SMatthew G. Knepley PetscInt sizes[4], numEntityBlocks, numTags, t, numNodes, numNodesBlock = 0, block, node, n; 92081a1af93SMatthew G. Knepley GmshEntity *entity = NULL; 9210598e1a2SLisandro Dalcin GmshNodes *nodes; 922698a79b9SLisandro Dalcin 923698a79b9SLisandro Dalcin PetscFunctionBegin; 9249566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, sizes, 4)); 9259371c9d4SSatish Balay numEntityBlocks = sizes[0]; 9269371c9d4SSatish Balay numNodes = sizes[1]; 9279566063dSJacob Faibussowitsch PetscCall(GmshNodesCreate(numNodes, &nodes)); 9280598e1a2SLisandro Dalcin mesh->numNodes = numNodes; 9290598e1a2SLisandro Dalcin mesh->nodelist = nodes; 930698a79b9SLisandro Dalcin for (block = 0, node = 0; block < numEntityBlocks; ++block, node += numNodesBlock) { 9319566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, info, 3)); 9329371c9d4SSatish Balay dim = info[0]; 9339371c9d4SSatish Balay eid = info[1]; 9349371c9d4SSatish Balay parametric = info[2]; 9359566063dSJacob Faibussowitsch PetscCall(GmshEntitiesGet(mesh->entities, dim, eid, &entity)); 9367d5b9244SMatthew G. Knepley numTags = entity->numTags; 93781a1af93SMatthew G. Knepley PetscCheck(!parametric, PETSC_COMM_SELF, PETSC_ERR_SUP, "Parametric coordinates not supported"); 9389566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, &numNodesBlock, 1)); 9399566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, nodes->id + node, numNodesBlock)); 9409566063dSJacob Faibussowitsch PetscCall(GmshReadDouble(gmsh, nodes->xyz + node * 3, numNodesBlock * 3)); 9417d5b9244SMatthew G. Knepley for (n = 0; n < numNodesBlock; ++n) { 9427d5b9244SMatthew G. Knepley PetscInt *tags = &nodes->tag[node * GMSH_MAX_TAGS]; 9437d5b9244SMatthew G. Knepley 9447d5b9244SMatthew G. Knepley for (t = 0; t < numTags; ++t) tags[n * GMSH_MAX_TAGS + t] = entity->tags[t]; 9457d5b9244SMatthew G. Knepley for (t = numTags; t < GMSH_MAX_TAGS; ++t) tags[n * GMSH_MAX_TAGS + t] = -1; 9467d5b9244SMatthew G. Knepley } 947698a79b9SLisandro Dalcin } 9480598e1a2SLisandro Dalcin gmsh->nodeStart = sizes[2]; 9490598e1a2SLisandro Dalcin gmsh->nodeEnd = sizes[3] + 1; 9503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 951698a79b9SLisandro Dalcin } 952698a79b9SLisandro Dalcin 95333a088b6SMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 954698a79b9SLisandro Dalcin $Elements 955698a79b9SLisandro Dalcin numEntityBlocks(size_t) numElements(size_t) 956698a79b9SLisandro Dalcin minElementTag(size_t) maxElementTag(size_t) 957698a79b9SLisandro Dalcin entityDim(int) entityTag(int) elementType(int; see below) numElementsBlock(size_t) 958698a79b9SLisandro Dalcin elementTag(size_t) nodeTag(size_t) ... 959698a79b9SLisandro Dalcin ... 960698a79b9SLisandro Dalcin ... 961698a79b9SLisandro Dalcin $EndElements 962698a79b9SLisandro Dalcin */ 963d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements_v41(GmshFile *gmsh, GmshMesh *mesh) 964d71ae5a4SJacob Faibussowitsch { 9650598e1a2SLisandro Dalcin int info[3], eid, dim, cellType; 9660598e1a2SLisandro Dalcin PetscInt sizes[4], *ibuf = NULL, numEntityBlocks, numElements, numBlockElements, numVerts, numNodes, numTags, block, elem, c, p; 967698a79b9SLisandro Dalcin GmshEntity *entity = NULL; 968698a79b9SLisandro Dalcin GmshElement *elements; 9690598e1a2SLisandro Dalcin PetscInt *nodeMap = gmsh->nodeMap; 970698a79b9SLisandro Dalcin 971698a79b9SLisandro Dalcin PetscFunctionBegin; 9729566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, sizes, 4)); 9739371c9d4SSatish Balay numEntityBlocks = sizes[0]; 9749371c9d4SSatish Balay numElements = sizes[1]; 9759566063dSJacob Faibussowitsch PetscCall(GmshElementsCreate(numElements, &elements)); 9760598e1a2SLisandro Dalcin mesh->numElems = numElements; 9770598e1a2SLisandro Dalcin mesh->elements = elements; 978698a79b9SLisandro Dalcin for (c = 0, block = 0; block < numEntityBlocks; ++block) { 9799566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, info, 3)); 9809371c9d4SSatish Balay dim = info[0]; 9819371c9d4SSatish Balay eid = info[1]; 9829371c9d4SSatish Balay cellType = info[2]; 9839566063dSJacob Faibussowitsch PetscCall(GmshEntitiesGet(mesh->entities, dim, eid, &entity)); 9849566063dSJacob Faibussowitsch PetscCall(GmshCellTypeCheck(cellType)); 9850598e1a2SLisandro Dalcin numVerts = GmshCellMap[cellType].numVerts; 9860598e1a2SLisandro Dalcin numNodes = GmshCellMap[cellType].numNodes; 9877d5b9244SMatthew G. Knepley numTags = entity->numTags; 9889566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, &numBlockElements, 1)); 9899566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, (1 + numNodes) * numBlockElements, sizeof(PetscInt), &ibuf)); 9909566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, ibuf, (1 + numNodes) * numBlockElements)); 991698a79b9SLisandro Dalcin for (elem = 0; elem < numBlockElements; ++elem, ++c) { 992698a79b9SLisandro Dalcin GmshElement *element = elements + c; 9930598e1a2SLisandro Dalcin const PetscInt *id = ibuf + elem * (1 + numNodes), *nodes = id + 1; 994698a79b9SLisandro Dalcin element->id = id[0]; 995698a79b9SLisandro Dalcin element->dim = dim; 996698a79b9SLisandro Dalcin element->cellType = cellType; 9970598e1a2SLisandro Dalcin element->numVerts = numVerts; 998698a79b9SLisandro Dalcin element->numNodes = numNodes; 999698a79b9SLisandro Dalcin element->numTags = numTags; 10009566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes)); 10010598e1a2SLisandro Dalcin for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]]; 10020598e1a2SLisandro Dalcin for (p = 0; p < element->numTags; p++) element->tags[p] = entity->tags[p]; 1003698a79b9SLisandro Dalcin } 1004698a79b9SLisandro Dalcin } 10053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1006698a79b9SLisandro Dalcin } 1007698a79b9SLisandro Dalcin 10080598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 1009698a79b9SLisandro Dalcin $Periodic 1010698a79b9SLisandro Dalcin numPeriodicLinks(size_t) 10119dddd249SSatish Balay entityDim(int) entityTag(int) entityTagPrimary(int) 1012698a79b9SLisandro Dalcin numAffine(size_t) value(double) ... 1013698a79b9SLisandro Dalcin numCorrespondingNodes(size_t) 10149dddd249SSatish Balay nodeTag(size_t) nodeTagPrimary(size_t) 1015698a79b9SLisandro Dalcin ... 1016698a79b9SLisandro Dalcin ... 1017698a79b9SLisandro Dalcin $EndPeriodic 1018698a79b9SLisandro Dalcin */ 1019d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPeriodic_v41(GmshFile *gmsh, PetscInt periodicMap[]) 1020d71ae5a4SJacob Faibussowitsch { 1021698a79b9SLisandro Dalcin int info[3]; 1022698a79b9SLisandro Dalcin double dbuf[16]; 10230598e1a2SLisandro Dalcin PetscInt numPeriodicLinks, numAffine, numCorrespondingNodes, *nodeTags = NULL, link, node; 10240598e1a2SLisandro Dalcin PetscInt *nodeMap = gmsh->nodeMap; 1025698a79b9SLisandro Dalcin 1026698a79b9SLisandro Dalcin PetscFunctionBegin; 10279566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, &numPeriodicLinks, 1)); 1028698a79b9SLisandro Dalcin for (link = 0; link < numPeriodicLinks; ++link) { 10299566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, info, 3)); 10309566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, &numAffine, 1)); 10319566063dSJacob Faibussowitsch PetscCall(GmshReadDouble(gmsh, dbuf, numAffine)); 10329566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, &numCorrespondingNodes, 1)); 10339566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, numCorrespondingNodes, sizeof(PetscInt), &nodeTags)); 10349566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, nodeTags, numCorrespondingNodes * 2)); 1035698a79b9SLisandro Dalcin for (node = 0; node < numCorrespondingNodes; ++node) { 10369dddd249SSatish Balay PetscInt correspondingNode = nodeMap[nodeTags[node * 2 + 0]]; 10379dddd249SSatish Balay PetscInt primaryNode = nodeMap[nodeTags[node * 2 + 1]]; 10389dddd249SSatish Balay periodicMap[correspondingNode] = primaryNode; 1039698a79b9SLisandro Dalcin } 1040698a79b9SLisandro Dalcin } 10413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1042698a79b9SLisandro Dalcin } 1043698a79b9SLisandro Dalcin 10440598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 1045d6689ca9SLisandro Dalcin $MeshFormat // same as MSH version 2 1046d6689ca9SLisandro Dalcin version(ASCII double; currently 4.1) 1047d6689ca9SLisandro Dalcin file-type(ASCII int; 0 for ASCII mode, 1 for binary mode) 1048d6689ca9SLisandro Dalcin data-size(ASCII int; sizeof(size_t)) 1049d6689ca9SLisandro Dalcin < int with value one; only in binary mode, to detect endianness > 1050d6689ca9SLisandro Dalcin $EndMeshFormat 1051d6689ca9SLisandro Dalcin */ 1052d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadMeshFormat(GmshFile *gmsh) 1053d71ae5a4SJacob Faibussowitsch { 1054698a79b9SLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 1055698a79b9SLisandro Dalcin int snum, fileType, fileFormat, dataSize, checkEndian; 1056698a79b9SLisandro Dalcin float version; 1057698a79b9SLisandro Dalcin 1058698a79b9SLisandro Dalcin PetscFunctionBegin; 10599566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 3)); 1060698a79b9SLisandro Dalcin snum = sscanf(line, "%f %d %d", &version, &fileType, &dataSize); 1061a8d4e440SJunchao Zhang fileFormat = (int)roundf(version * 10); 106208401ef6SPierre Jolivet PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line); 1063a8d4e440SJunchao Zhang PetscCheck(fileFormat >= 22, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at least 2.2", (double)version); 10641dca8a05SBarry Smith PetscCheck((int)version != 3, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f not supported", (double)version); 1065a8d4e440SJunchao Zhang PetscCheck(fileFormat <= 41, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at most 4.1", (double)version); 106608401ef6SPierre Jolivet PetscCheck(!gmsh->binary || fileType, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Viewer is binary but Gmsh file is ASCII"); 106708401ef6SPierre Jolivet PetscCheck(gmsh->binary || !fileType, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Viewer is ASCII but Gmsh file is binary"); 10681dca8a05SBarry 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); 10691dca8a05SBarry 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); 1070698a79b9SLisandro Dalcin gmsh->fileFormat = fileFormat; 1071698a79b9SLisandro Dalcin gmsh->dataSize = dataSize; 1072698a79b9SLisandro Dalcin gmsh->byteSwap = PETSC_FALSE; 1073698a79b9SLisandro Dalcin if (gmsh->binary) { 10749566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, &checkEndian, 1)); 1075698a79b9SLisandro Dalcin if (checkEndian != 1) { 10769566063dSJacob Faibussowitsch PetscCall(PetscByteSwap(&checkEndian, PETSC_ENUM, 1)); 107708401ef6SPierre Jolivet PetscCheck(checkEndian == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to detect endianness in Gmsh file header: %s", line); 1078698a79b9SLisandro Dalcin gmsh->byteSwap = PETSC_TRUE; 1079698a79b9SLisandro Dalcin } 1080698a79b9SLisandro Dalcin } 10813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1082698a79b9SLisandro Dalcin } 1083698a79b9SLisandro Dalcin 10848749820aSMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 10858749820aSMatthew G. Knepley Neper: https://neper.info/ adds this section 10868749820aSMatthew G. Knepley 10878749820aSMatthew G. Knepley $MeshVersion 10888749820aSMatthew G. Knepley <major>.<minor>,<patch> 10898749820aSMatthew G. Knepley $EndMeshVersion 10908749820aSMatthew G. Knepley */ 10918749820aSMatthew G. Knepley static PetscErrorCode GmshReadMeshVersion(GmshFile *gmsh) 10928749820aSMatthew G. Knepley { 10938749820aSMatthew G. Knepley char line[PETSC_MAX_PATH_LEN]; 10948749820aSMatthew G. Knepley int snum, major, minor, patch; 10958749820aSMatthew G. Knepley 10968749820aSMatthew G. Knepley PetscFunctionBegin; 10978749820aSMatthew G. Knepley PetscCall(GmshReadString(gmsh, line, 1)); 10988749820aSMatthew G. Knepley snum = sscanf(line, "%d.%d.%d", &major, &minor, &patch); 10998749820aSMatthew G. Knepley PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line); 11008749820aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 11018749820aSMatthew G. Knepley } 11028749820aSMatthew G. Knepley 11038749820aSMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 11048749820aSMatthew G. Knepley Neper: https://neper.info/ adds this section 11058749820aSMatthew G. Knepley 11068749820aSMatthew G. Knepley $Domain 11078749820aSMatthew G. Knepley <shape> 11088749820aSMatthew G. Knepley $EndDomain 11098749820aSMatthew G. Knepley */ 11108749820aSMatthew G. Knepley static PetscErrorCode GmshReadMeshDomain(GmshFile *gmsh) 11118749820aSMatthew G. Knepley { 11128749820aSMatthew G. Knepley char line[PETSC_MAX_PATH_LEN]; 11138749820aSMatthew G. Knepley 11148749820aSMatthew G. Knepley PetscFunctionBegin; 11158749820aSMatthew G. Knepley PetscCall(GmshReadString(gmsh, line, 1)); 11168749820aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 11178749820aSMatthew G. Knepley } 11188749820aSMatthew G. Knepley 11191f643af3SLisandro Dalcin /* 11201f643af3SLisandro Dalcin PhysicalNames 11211f643af3SLisandro Dalcin numPhysicalNames(ASCII int) 11221f643af3SLisandro Dalcin dimension(ASCII int) physicalTag(ASCII int) "name"(127 characters max) 11231f643af3SLisandro Dalcin ... 11241f643af3SLisandro Dalcin $EndPhysicalNames 11251f643af3SLisandro Dalcin */ 1126d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPhysicalNames(GmshFile *gmsh, GmshMesh *mesh) 1127d71ae5a4SJacob Faibussowitsch { 1128bbcf679cSJacob Faibussowitsch char line[PETSC_MAX_PATH_LEN], name[128 + 2], *p = NULL, *q = NULL, *r = NULL; 1129a45dabc8SMatthew G. Knepley int snum, region, dim, tag; 1130698a79b9SLisandro Dalcin 1131698a79b9SLisandro Dalcin PetscFunctionBegin; 11329566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 1)); 1133a45dabc8SMatthew G. Knepley snum = sscanf(line, "%d", ®ion); 1134a45dabc8SMatthew G. Knepley mesh->numRegions = region; 113508401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 113690d778b8SLisandro Dalcin PetscCall(PetscMalloc3(mesh->numRegions, &mesh->regionDims, mesh->numRegions, &mesh->regionTags, mesh->numRegions, &mesh->regionNames)); 1137a45dabc8SMatthew G. Knepley for (region = 0; region < mesh->numRegions; ++region) { 11389566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 2)); 11391f643af3SLisandro Dalcin snum = sscanf(line, "%d %d", &dim, &tag); 114008401ef6SPierre Jolivet PetscCheck(snum == 2, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 11419566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, -(PetscInt)sizeof(line))); 11429566063dSJacob Faibussowitsch PetscCall(PetscStrchr(line, '"', &p)); 114328b400f6SJacob Faibussowitsch PetscCheck(p, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 11449566063dSJacob Faibussowitsch PetscCall(PetscStrrchr(line, '"', &q)); 114508401ef6SPierre Jolivet PetscCheck(q != p, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 11465f5cd6d5SMatthew G. Knepley PetscCall(PetscStrrchr(line, ':', &r)); 11475f5cd6d5SMatthew G. Knepley if (p != r) q = r; 11489566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(name, p + 1, (size_t)(q - p - 1))); 114990d778b8SLisandro Dalcin mesh->regionDims[region] = dim; 1150a45dabc8SMatthew G. Knepley mesh->regionTags[region] = tag; 11519566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(name, &mesh->regionNames[region])); 1152698a79b9SLisandro Dalcin } 11533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1154de78e4feSLisandro Dalcin } 1155de78e4feSLisandro Dalcin 1156d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEntities(GmshFile *gmsh, GmshMesh *mesh) 1157d71ae5a4SJacob Faibussowitsch { 11580598e1a2SLisandro Dalcin PetscFunctionBegin; 11590598e1a2SLisandro Dalcin switch (gmsh->fileFormat) { 1160d71ae5a4SJacob Faibussowitsch case 41: 1161d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadEntities_v41(gmsh, mesh)); 1162d71ae5a4SJacob Faibussowitsch break; 1163d71ae5a4SJacob Faibussowitsch default: 1164d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadEntities_v40(gmsh, mesh)); 1165d71ae5a4SJacob Faibussowitsch break; 116696ca5757SLisandro Dalcin } 11673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11680598e1a2SLisandro Dalcin } 11690598e1a2SLisandro Dalcin 1170d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes(GmshFile *gmsh, GmshMesh *mesh) 1171d71ae5a4SJacob Faibussowitsch { 11720598e1a2SLisandro Dalcin PetscFunctionBegin; 11730598e1a2SLisandro Dalcin switch (gmsh->fileFormat) { 1174d71ae5a4SJacob Faibussowitsch case 41: 1175d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadNodes_v41(gmsh, mesh)); 1176d71ae5a4SJacob Faibussowitsch break; 1177d71ae5a4SJacob Faibussowitsch case 40: 1178d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadNodes_v40(gmsh, mesh)); 1179d71ae5a4SJacob Faibussowitsch break; 1180d71ae5a4SJacob Faibussowitsch default: 1181d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadNodes_v22(gmsh, mesh)); 1182d71ae5a4SJacob Faibussowitsch break; 11830598e1a2SLisandro Dalcin } 11840598e1a2SLisandro Dalcin 11850598e1a2SLisandro Dalcin { /* Gmsh v2.2/v4.0 does not provide min/max node tags */ 11860598e1a2SLisandro Dalcin if (mesh->numNodes > 0 && gmsh->nodeEnd >= gmsh->nodeStart) { 11870598e1a2SLisandro Dalcin PetscInt tagMin = PETSC_MAX_INT, tagMax = PETSC_MIN_INT, n; 11880598e1a2SLisandro Dalcin GmshNodes *nodes = mesh->nodelist; 11890598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) { 11900598e1a2SLisandro Dalcin const PetscInt tag = nodes->id[n]; 11910598e1a2SLisandro Dalcin tagMin = PetscMin(tag, tagMin); 11920598e1a2SLisandro Dalcin tagMax = PetscMax(tag, tagMax); 11930598e1a2SLisandro Dalcin } 11940598e1a2SLisandro Dalcin gmsh->nodeStart = tagMin; 11950598e1a2SLisandro Dalcin gmsh->nodeEnd = tagMax + 1; 11960598e1a2SLisandro Dalcin } 11970598e1a2SLisandro Dalcin } 11980598e1a2SLisandro Dalcin 11990598e1a2SLisandro Dalcin { /* Support for sparse node tags */ 12000598e1a2SLisandro Dalcin PetscInt n, t; 12010598e1a2SLisandro Dalcin GmshNodes *nodes = mesh->nodelist; 12029566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(gmsh->nodeEnd - gmsh->nodeStart, &gmsh->nbuf)); 12030598e1a2SLisandro Dalcin for (t = 0; t < gmsh->nodeEnd - gmsh->nodeStart; ++t) gmsh->nbuf[t] = PETSC_MIN_INT; 12040598e1a2SLisandro Dalcin gmsh->nodeMap = gmsh->nbuf - gmsh->nodeStart; 12050598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) { 12060598e1a2SLisandro Dalcin const PetscInt tag = nodes->id[n]; 120763a3b9bcSJacob Faibussowitsch PetscCheck(gmsh->nodeMap[tag] < 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Repeated node tag %" PetscInt_FMT, tag); 12080598e1a2SLisandro Dalcin gmsh->nodeMap[tag] = n; 12090598e1a2SLisandro Dalcin } 12100598e1a2SLisandro Dalcin } 12113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12120598e1a2SLisandro Dalcin } 12130598e1a2SLisandro Dalcin 1214d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements(GmshFile *gmsh, GmshMesh *mesh) 1215d71ae5a4SJacob Faibussowitsch { 12160598e1a2SLisandro Dalcin PetscFunctionBegin; 12170598e1a2SLisandro Dalcin switch (gmsh->fileFormat) { 1218d71ae5a4SJacob Faibussowitsch case 41: 1219d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadElements_v41(gmsh, mesh)); 1220d71ae5a4SJacob Faibussowitsch break; 1221d71ae5a4SJacob Faibussowitsch case 40: 1222d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadElements_v40(gmsh, mesh)); 1223d71ae5a4SJacob Faibussowitsch break; 1224d71ae5a4SJacob Faibussowitsch default: 1225d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadElements_v22(gmsh, mesh)); 1226d71ae5a4SJacob Faibussowitsch break; 12270598e1a2SLisandro Dalcin } 12280598e1a2SLisandro Dalcin 12290598e1a2SLisandro Dalcin { /* Reorder elements by codimension and polytope type */ 12300598e1a2SLisandro Dalcin PetscInt ne = mesh->numElems; 12310598e1a2SLisandro Dalcin GmshElement *elements = mesh->elements; 1232066ea43fSLisandro Dalcin PetscInt keymap[GMSH_NUM_POLYTOPES], nk = 0; 1233066ea43fSLisandro Dalcin PetscInt offset[GMSH_NUM_POLYTOPES + 1], e, k; 12340598e1a2SLisandro Dalcin 1235066ea43fSLisandro Dalcin for (k = 0; k < GMSH_NUM_POLYTOPES; ++k) keymap[k] = PETSC_MIN_INT; 12369566063dSJacob Faibussowitsch PetscCall(PetscMemzero(offset, sizeof(offset))); 12370598e1a2SLisandro Dalcin 1238066ea43fSLisandro Dalcin keymap[GMSH_TET] = nk++; 1239066ea43fSLisandro Dalcin keymap[GMSH_HEX] = nk++; 1240066ea43fSLisandro Dalcin keymap[GMSH_PRI] = nk++; 1241066ea43fSLisandro Dalcin keymap[GMSH_PYR] = nk++; 1242066ea43fSLisandro Dalcin keymap[GMSH_TRI] = nk++; 1243066ea43fSLisandro Dalcin keymap[GMSH_QUA] = nk++; 1244066ea43fSLisandro Dalcin keymap[GMSH_SEG] = nk++; 1245066ea43fSLisandro Dalcin keymap[GMSH_VTX] = nk++; 12460598e1a2SLisandro Dalcin 12479566063dSJacob Faibussowitsch PetscCall(GmshElementsCreate(mesh->numElems, &mesh->elements)); 12484ad8454bSPierre Jolivet #define key(eid) keymap[GmshCellMap[elements[eid].cellType].polytope] 12490598e1a2SLisandro Dalcin for (e = 0; e < ne; ++e) offset[1 + key(e)]++; 12500598e1a2SLisandro Dalcin for (k = 1; k < nk; ++k) offset[k] += offset[k - 1]; 12510598e1a2SLisandro Dalcin for (e = 0; e < ne; ++e) mesh->elements[offset[key(e)]++] = elements[e]; 12520598e1a2SLisandro Dalcin #undef key 12539566063dSJacob Faibussowitsch PetscCall(GmshElementsDestroy(&elements)); 1254066ea43fSLisandro Dalcin } 12550598e1a2SLisandro Dalcin 1256066ea43fSLisandro Dalcin { /* Mesh dimension and order */ 1257066ea43fSLisandro Dalcin GmshElement *elem = mesh->numElems ? mesh->elements : NULL; 1258066ea43fSLisandro Dalcin mesh->dim = elem ? GmshCellMap[elem->cellType].dim : 0; 1259066ea43fSLisandro Dalcin mesh->order = elem ? GmshCellMap[elem->cellType].order : 0; 12600598e1a2SLisandro Dalcin } 12610598e1a2SLisandro Dalcin 12620598e1a2SLisandro Dalcin { 12630598e1a2SLisandro Dalcin PetscBT vtx; 12640598e1a2SLisandro Dalcin PetscInt dim = mesh->dim, e, n, v; 12650598e1a2SLisandro Dalcin 12669566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(mesh->numNodes, &vtx)); 12670598e1a2SLisandro Dalcin 12680598e1a2SLisandro Dalcin /* Compute number of cells and set of vertices */ 12690598e1a2SLisandro Dalcin mesh->numCells = 0; 12700598e1a2SLisandro Dalcin for (e = 0; e < mesh->numElems; ++e) { 12710598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + e; 12720598e1a2SLisandro Dalcin if (elem->dim == dim && dim > 0) mesh->numCells++; 127348a46eb9SPierre Jolivet for (v = 0; v < elem->numVerts; v++) PetscCall(PetscBTSet(vtx, elem->nodes[v])); 12740598e1a2SLisandro Dalcin } 12750598e1a2SLisandro Dalcin 12760598e1a2SLisandro Dalcin /* Compute numbering for vertices */ 12770598e1a2SLisandro Dalcin mesh->numVerts = 0; 12789566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mesh->numNodes, &mesh->vertexMap)); 12799371c9d4SSatish Balay for (n = 0; n < mesh->numNodes; ++n) mesh->vertexMap[n] = PetscBTLookup(vtx, n) ? mesh->numVerts++ : PETSC_MIN_INT; 12800598e1a2SLisandro Dalcin 12819566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&vtx)); 12820598e1a2SLisandro Dalcin } 12833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12840598e1a2SLisandro Dalcin } 12850598e1a2SLisandro Dalcin 1286d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPeriodic(GmshFile *gmsh, GmshMesh *mesh) 1287d71ae5a4SJacob Faibussowitsch { 12880598e1a2SLisandro Dalcin PetscInt n; 12890598e1a2SLisandro Dalcin 12900598e1a2SLisandro Dalcin PetscFunctionBegin; 12919566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mesh->numNodes, &mesh->periodMap)); 12920598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) mesh->periodMap[n] = n; 12930598e1a2SLisandro Dalcin switch (gmsh->fileFormat) { 1294d71ae5a4SJacob Faibussowitsch case 41: 1295d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadPeriodic_v41(gmsh, mesh->periodMap)); 1296d71ae5a4SJacob Faibussowitsch break; 1297d71ae5a4SJacob Faibussowitsch default: 1298d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadPeriodic_v40(gmsh, mesh->periodMap)); 1299d71ae5a4SJacob Faibussowitsch break; 13000598e1a2SLisandro Dalcin } 13010598e1a2SLisandro Dalcin 13029dddd249SSatish Balay /* Find canonical primary nodes */ 13030598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) 13049371c9d4SSatish Balay while (mesh->periodMap[n] != mesh->periodMap[mesh->periodMap[n]]) mesh->periodMap[n] = mesh->periodMap[mesh->periodMap[n]]; 13050598e1a2SLisandro Dalcin 13069dddd249SSatish Balay /* Renumber vertices (filter out correspondings) */ 13070598e1a2SLisandro Dalcin mesh->numVerts = 0; 13080598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) 13090598e1a2SLisandro Dalcin if (mesh->vertexMap[n] >= 0) /* is vertex */ 13109dddd249SSatish Balay if (mesh->periodMap[n] == n) /* is primary */ 13110598e1a2SLisandro Dalcin mesh->vertexMap[n] = mesh->numVerts++; 13120598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) 13130598e1a2SLisandro Dalcin if (mesh->vertexMap[n] >= 0) /* is vertex */ 13149dddd249SSatish Balay if (mesh->periodMap[n] != n) /* is corresponding */ 13150598e1a2SLisandro Dalcin mesh->vertexMap[n] = mesh->vertexMap[mesh->periodMap[n]]; 13163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13170598e1a2SLisandro Dalcin } 13180598e1a2SLisandro Dalcin 1319066ea43fSLisandro Dalcin #define DM_POLYTOPE_VERTEX DM_POLYTOPE_POINT 1320066ea43fSLisandro Dalcin static const DMPolytopeType DMPolytopeMap[] = { 1321066ea43fSLisandro Dalcin /* GMSH_VTX */ DM_POLYTOPE_VERTEX, 1322066ea43fSLisandro Dalcin /* GMSH_SEG */ DM_POLYTOPE_SEGMENT, 1323066ea43fSLisandro Dalcin /* GMSH_TRI */ DM_POLYTOPE_TRIANGLE, 1324066ea43fSLisandro Dalcin /* GMSH_QUA */ DM_POLYTOPE_QUADRILATERAL, 1325066ea43fSLisandro Dalcin /* GMSH_TET */ DM_POLYTOPE_TETRAHEDRON, 1326066ea43fSLisandro Dalcin /* GMSH_HEX */ DM_POLYTOPE_HEXAHEDRON, 1327066ea43fSLisandro Dalcin /* GMSH_PRI */ DM_POLYTOPE_TRI_PRISM, 13289371c9d4SSatish Balay /* GMSH_PYR */ DM_POLYTOPE_PYRAMID, DM_POLYTOPE_UNKNOWN}; 13290598e1a2SLisandro Dalcin 1330d71ae5a4SJacob Faibussowitsch static inline DMPolytopeType DMPolytopeTypeFromGmsh(PetscInt cellType) 1331d71ae5a4SJacob Faibussowitsch { 1332066ea43fSLisandro Dalcin return DMPolytopeMap[GmshCellMap[cellType].polytope]; 1333066ea43fSLisandro Dalcin } 1334066ea43fSLisandro Dalcin 1335d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshCreateFE(MPI_Comm comm, const char prefix[], PetscBool isSimplex, PetscBool continuity, PetscDTNodeType nodeType, PetscInt dim, PetscInt Nc, PetscInt k, PetscFE *fem) 1336d71ae5a4SJacob Faibussowitsch { 1337066ea43fSLisandro Dalcin DM K; 1338066ea43fSLisandro Dalcin PetscSpace P; 1339066ea43fSLisandro Dalcin PetscDualSpace Q; 1340066ea43fSLisandro Dalcin PetscQuadrature q, fq; 1341066ea43fSLisandro Dalcin PetscBool isTensor = isSimplex ? PETSC_FALSE : PETSC_TRUE; 1342066ea43fSLisandro Dalcin PetscBool endpoint = PETSC_TRUE; 1343066ea43fSLisandro Dalcin char name[32]; 1344066ea43fSLisandro Dalcin 1345066ea43fSLisandro Dalcin PetscFunctionBegin; 1346066ea43fSLisandro Dalcin /* Create space */ 13479566063dSJacob Faibussowitsch PetscCall(PetscSpaceCreate(comm, &P)); 13489566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetType(P, PETSCSPACEPOLYNOMIAL)); 13499566063dSJacob Faibussowitsch PetscCall(PetscSpacePolynomialSetTensor(P, isTensor)); 13509566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumComponents(P, Nc)); 13519566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumVariables(P, dim)); 13529566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetDegree(P, k, PETSC_DETERMINE)); 1353066ea43fSLisandro Dalcin if (prefix) { 13549566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)P, prefix)); 13559566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetFromOptions(P)); 13569566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)P, NULL)); 13579566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetDegree(P, &k, NULL)); 1358066ea43fSLisandro Dalcin } 13599566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetUp(P)); 1360066ea43fSLisandro Dalcin /* Create dual space */ 13619566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceCreate(comm, &Q)); 13629566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetType(Q, PETSCDUALSPACELAGRANGE)); 13639566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceLagrangeSetTensor(Q, isTensor)); 13649566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceLagrangeSetContinuity(Q, continuity)); 13659566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceLagrangeSetNodeType(Q, nodeType, endpoint, 0)); 13669566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetNumComponents(Q, Nc)); 13679566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetOrder(Q, k)); 13689566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell(PETSC_COMM_SELF, DMPolytopeTypeSimpleShape(dim, isSimplex), &K)); 13699566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetDM(Q, K)); 13709566063dSJacob Faibussowitsch PetscCall(DMDestroy(&K)); 1371066ea43fSLisandro Dalcin if (prefix) { 13729566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)Q, prefix)); 13739566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetFromOptions(Q)); 13749566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)Q, NULL)); 1375066ea43fSLisandro Dalcin } 13769566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetUp(Q)); 1377066ea43fSLisandro Dalcin /* Create quadrature */ 1378066ea43fSLisandro Dalcin if (isSimplex) { 13799566063dSJacob Faibussowitsch PetscCall(PetscDTStroudConicalQuadrature(dim, 1, k + 1, -1, +1, &q)); 13809566063dSJacob Faibussowitsch PetscCall(PetscDTStroudConicalQuadrature(dim - 1, 1, k + 1, -1, +1, &fq)); 1381066ea43fSLisandro Dalcin } else { 13829566063dSJacob Faibussowitsch PetscCall(PetscDTGaussTensorQuadrature(dim, 1, k + 1, -1, +1, &q)); 13839566063dSJacob Faibussowitsch PetscCall(PetscDTGaussTensorQuadrature(dim - 1, 1, k + 1, -1, +1, &fq)); 1384066ea43fSLisandro Dalcin } 1385066ea43fSLisandro Dalcin /* Create finite element */ 13869566063dSJacob Faibussowitsch PetscCall(PetscFECreate(comm, fem)); 13879566063dSJacob Faibussowitsch PetscCall(PetscFESetType(*fem, PETSCFEBASIC)); 13889566063dSJacob Faibussowitsch PetscCall(PetscFESetNumComponents(*fem, Nc)); 13899566063dSJacob Faibussowitsch PetscCall(PetscFESetBasisSpace(*fem, P)); 13909566063dSJacob Faibussowitsch PetscCall(PetscFESetDualSpace(*fem, Q)); 13919566063dSJacob Faibussowitsch PetscCall(PetscFESetQuadrature(*fem, q)); 13929566063dSJacob Faibussowitsch PetscCall(PetscFESetFaceQuadrature(*fem, fq)); 1393066ea43fSLisandro Dalcin if (prefix) { 13949566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*fem, prefix)); 13959566063dSJacob Faibussowitsch PetscCall(PetscFESetFromOptions(*fem)); 13969566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*fem, NULL)); 1397066ea43fSLisandro Dalcin } 13989566063dSJacob Faibussowitsch PetscCall(PetscFESetUp(*fem)); 1399066ea43fSLisandro Dalcin /* Cleanup */ 14009566063dSJacob Faibussowitsch PetscCall(PetscSpaceDestroy(&P)); 14019566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceDestroy(&Q)); 14029566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&q)); 14039566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&fq)); 1404066ea43fSLisandro Dalcin /* Set finite element name */ 140563a3b9bcSJacob Faibussowitsch PetscCall(PetscSNPrintf(name, sizeof(name), "%s%" PetscInt_FMT, isSimplex ? "P" : "Q", k)); 14069566063dSJacob Faibussowitsch PetscCall(PetscFESetName(*fem, name)); 14073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 140896ca5757SLisandro Dalcin } 140996ca5757SLisandro Dalcin 1410d6689ca9SLisandro Dalcin /*@C 1411a1cb98faSBarry Smith DMPlexCreateGmshFromFile - Create a `DMPLEX` mesh from a Gmsh file 1412d6689ca9SLisandro Dalcin 1413a4e35b19SJacob Faibussowitsch Input Parameters: 1414d6689ca9SLisandro Dalcin + comm - The MPI communicator 1415d6689ca9SLisandro Dalcin . filename - Name of the Gmsh file 1416d6689ca9SLisandro Dalcin - interpolate - Create faces and edges in the mesh 1417d6689ca9SLisandro Dalcin 1418d6689ca9SLisandro Dalcin Output Parameter: 1419a1cb98faSBarry Smith . dm - The `DM` object representing the mesh 1420d6689ca9SLisandro Dalcin 1421d6689ca9SLisandro Dalcin Level: beginner 1422d6689ca9SLisandro Dalcin 14231cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()` 1424d6689ca9SLisandro Dalcin @*/ 1425d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateGmshFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) 1426d71ae5a4SJacob Faibussowitsch { 1427d6689ca9SLisandro Dalcin PetscViewer viewer; 1428d6689ca9SLisandro Dalcin PetscMPIInt rank; 1429d6689ca9SLisandro Dalcin int fileType; 1430d6689ca9SLisandro Dalcin PetscViewerType vtype; 1431d6689ca9SLisandro Dalcin 1432d6689ca9SLisandro Dalcin PetscFunctionBegin; 14339566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1434d6689ca9SLisandro Dalcin 1435d6689ca9SLisandro Dalcin /* Determine Gmsh file type (ASCII or binary) from file header */ 1436dd400576SPatrick Sanan if (rank == 0) { 14370598e1a2SLisandro Dalcin GmshFile gmsh[1]; 1438d6689ca9SLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 1439d6689ca9SLisandro Dalcin int snum; 1440d6689ca9SLisandro Dalcin float version; 1441a8d4e440SJunchao Zhang int fileFormat; 1442d6689ca9SLisandro Dalcin 14439566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(gmsh, 1)); 14449566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(PETSC_COMM_SELF, &gmsh->viewer)); 14459566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(gmsh->viewer, PETSCVIEWERASCII)); 14469566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(gmsh->viewer, FILE_MODE_READ)); 14479566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(gmsh->viewer, filename)); 1448d6689ca9SLisandro Dalcin /* Read only the first two lines of the Gmsh file */ 14499566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 14509566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$MeshFormat", line)); 14519566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 2)); 1452d6689ca9SLisandro Dalcin snum = sscanf(line, "%f %d", &version, &fileType); 1453a8d4e440SJunchao Zhang fileFormat = (int)roundf(version * 10); 145408401ef6SPierre Jolivet PetscCheck(snum == 2, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line); 1455a8d4e440SJunchao Zhang PetscCheck(fileFormat >= 22, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at least 2.2", (double)version); 14561dca8a05SBarry Smith PetscCheck((int)version != 3, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f not supported", (double)version); 1457a8d4e440SJunchao Zhang PetscCheck(fileFormat <= 41, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at most 4.1", (double)version); 14589566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&gmsh->viewer)); 1459d6689ca9SLisandro Dalcin } 14609566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&fileType, 1, MPI_INT, 0, comm)); 1461d6689ca9SLisandro Dalcin vtype = (fileType == 0) ? PETSCVIEWERASCII : PETSCVIEWERBINARY; 1462d6689ca9SLisandro Dalcin 1463d6689ca9SLisandro Dalcin /* Create appropriate viewer and build plex */ 14649566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 14659566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, vtype)); 14669566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 14679566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 14689566063dSJacob Faibussowitsch PetscCall(DMPlexCreateGmsh(comm, viewer, interpolate, dm)); 14699566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 14703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1471d6689ca9SLisandro Dalcin } 1472d6689ca9SLisandro Dalcin 1473331830f3SMatthew G. Knepley /*@ 1474a1cb98faSBarry Smith DMPlexCreateGmsh - Create a `DMPLEX` mesh from a Gmsh file viewer 1475331830f3SMatthew G. Knepley 1476d083f849SBarry Smith Collective 1477331830f3SMatthew G. Knepley 1478331830f3SMatthew G. Knepley Input Parameters: 1479331830f3SMatthew G. Knepley + comm - The MPI communicator 1480a1cb98faSBarry Smith . viewer - The `PetscViewer` associated with a Gmsh file 1481331830f3SMatthew G. Knepley - interpolate - Create faces and edges in the mesh 1482331830f3SMatthew G. Knepley 1483331830f3SMatthew G. Knepley Output Parameter: 1484a1cb98faSBarry Smith . dm - The `DM` object representing the mesh 1485331830f3SMatthew G. Knepley 1486a1cb98faSBarry Smith Options Database Keys: 1487df93260fSMatthew G. Knepley + -dm_plex_gmsh_hybrid - Force triangular prisms to use tensor order 1488df93260fSMatthew G. Knepley . -dm_plex_gmsh_periodic - Read Gmsh periodic section and construct a periodic Plex 1489df93260fSMatthew G. Knepley . -dm_plex_gmsh_highorder - Generate high-order coordinates 1490df93260fSMatthew 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 14912b205333SMatthew G. Knepley . -dm_plex_gmsh_use_generic - Generate generic labels, i.e. Cell Sets, Face Sets, etc. 1492df93260fSMatthew G. Knepley . -dm_plex_gmsh_use_regions - Generate labels with region names 1493df93260fSMatthew G. Knepley . -dm_plex_gmsh_mark_vertices - Add vertices to generated labels 1494df93260fSMatthew G. Knepley . -dm_plex_gmsh_multiple_tags - Allow multiple tags for default labels 1495df93260fSMatthew G. Knepley - -dm_plex_gmsh_spacedim <d> - Embedding space dimension, if different from topological dimension 1496df93260fSMatthew G. Knepley 14971d27aa22SBarry Smith Level: beginner 14981d27aa22SBarry Smith 14991d27aa22SBarry Smith Notes: 15001d27aa22SBarry Smith The Gmsh file format is described in <http://gmsh.info/doc/texinfo/gmsh.html#MSH-file-format> 1501df93260fSMatthew G. Knepley 15022b205333SMatthew G. Knepley By default, the "Cell Sets", "Face Sets", and "Vertex Sets" labels are created, and only insert the first tag on a point. By using -dm_plex_gmsh_multiple_tags, all tags can be inserted. Alternatively, -dm_plex_gmsh_use_regions creates labels based on the region names from the PhysicalNames section, and all tags are used, but you can retain the generic labels using -dm_plex_gmsh_use_generic. 1503331830f3SMatthew G. Knepley 15041cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()` 1505331830f3SMatthew G. Knepley @*/ 1506d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateGmsh(MPI_Comm comm, PetscViewer viewer, PetscBool interpolate, DM *dm) 1507d71ae5a4SJacob Faibussowitsch { 15080598e1a2SLisandro Dalcin GmshMesh *mesh = NULL; 150911c56cb0SLisandro Dalcin PetscViewer parentviewer = NULL; 15100598e1a2SLisandro Dalcin PetscBT periodicVerts = NULL; 1511eae3dc7dSJacob Faibussowitsch PetscBT *periodicCells = NULL; 15126858538eSMatthew G. Knepley DM cdm, cdmCell = NULL; 15136858538eSMatthew G. Knepley PetscSection cs, csCell = NULL; 15146858538eSMatthew G. Knepley Vec coordinates, coordinatesCell; 15150444adf6SMatthew G. Knepley DMLabel cellSets = NULL, faceSets = NULL, edgeSets = NULL, vertSets = NULL, marker = NULL, *regionSets; 15169db5b827SMatthew G. Knepley PetscInt dim = 0, coordDim = -1, order = 0, maxHeight = 0; 15179db5b827SMatthew G. Knepley PetscInt numNodes = 0, numElems = 0, numVerts = 0, numCells = 0, vStart, vEnd; 1518066ea43fSLisandro Dalcin PetscInt cell, cone[8], e, n, v, d; 15192b205333SMatthew G. Knepley PetscBool usegeneric = PETSC_TRUE, useregions = PETSC_FALSE, markvertices = PETSC_FALSE, multipleTags = PETSC_FALSE; 15202b205333SMatthew G. Knepley PetscBool flg, binary, hybrid = interpolate, periodic = PETSC_TRUE; 1521066ea43fSLisandro Dalcin PetscBool highOrder = PETSC_TRUE, highOrderSet, project = PETSC_FALSE; 1522066ea43fSLisandro Dalcin PetscBool isSimplex = PETSC_FALSE, isHybrid = PETSC_FALSE, hasTetra = PETSC_FALSE; 15230598e1a2SLisandro Dalcin PetscMPIInt rank; 1524331830f3SMatthew G. Knepley 1525331830f3SMatthew G. Knepley PetscFunctionBegin; 15269566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1527d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)viewer); 1528d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Gmsh options"); 1529df93260fSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_gmsh_hybrid", "Force triangular prisms to use tensor order", "DMPlexCreateGmsh", hybrid, &hybrid, NULL)); 15309566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_periodic", "Read Gmsh periodic section", "DMPlexCreateGmsh", periodic, &periodic, NULL)); 15319566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_highorder", "Generate high-order coordinates", "DMPlexCreateGmsh", highOrder, &highOrder, &highOrderSet)); 15329566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_project", "Project high-order coordinates to a different space", "DMPlexCreateGmsh", project, &project, NULL)); 15339566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_use_regions", "Generate labels with region names", "DMPlexCreateGmsh", useregions, &useregions, NULL)); 15342b205333SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_gmsh_use_generic", "Generate generic labels, i.e. Cell Sets, Face Sets, etc", "DMPlexCreateGmsh", usegeneric, &usegeneric, &flg)); 15352b205333SMatthew G. Knepley if (!flg && useregions) usegeneric = PETSC_FALSE; 15369566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_mark_vertices", "Add vertices to generated labels", "DMPlexCreateGmsh", markvertices, &markvertices, NULL)); 1537df93260fSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_gmsh_multiple_tags", "Allow multiple tags for default labels", "DMPlexCreateGmsh", multipleTags, &multipleTags, NULL)); 15389566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_gmsh_spacedim", "Embedding space dimension", "DMPlexCreateGmsh", coordDim, &coordDim, NULL, PETSC_DECIDE)); 15399db5b827SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_localize_height", "Localize edges and faces in addition to cells", "", maxHeight, &maxHeight, NULL, 0)); 1540d0609cedSBarry Smith PetscOptionsHeadEnd(); 1541d0609cedSBarry Smith PetscOptionsEnd(); 15420598e1a2SLisandro Dalcin 15439566063dSJacob Faibussowitsch PetscCall(GmshCellInfoSetUp()); 154411c56cb0SLisandro Dalcin 15459566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 15469566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 15479566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CreateGmsh, *dm, NULL, NULL, NULL)); 154811c56cb0SLisandro Dalcin 15499566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &binary)); 155011c56cb0SLisandro Dalcin 155111c56cb0SLisandro Dalcin /* Binary viewers read on all ranks, get subviewer to read only in rank 0 */ 15523b46f529SLisandro Dalcin if (binary) { 155311c56cb0SLisandro Dalcin parentviewer = viewer; 15549566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(parentviewer, PETSC_COMM_SELF, &viewer)); 155511c56cb0SLisandro Dalcin } 155611c56cb0SLisandro Dalcin 1557dd400576SPatrick Sanan if (rank == 0) { 15580598e1a2SLisandro Dalcin GmshFile gmsh[1]; 1559698a79b9SLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 1560698a79b9SLisandro Dalcin PetscBool match; 1561331830f3SMatthew G. Knepley 15629566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(gmsh, 1)); 1563698a79b9SLisandro Dalcin gmsh->viewer = viewer; 1564698a79b9SLisandro Dalcin gmsh->binary = binary; 1565698a79b9SLisandro Dalcin 15669566063dSJacob Faibussowitsch PetscCall(GmshMeshCreate(&mesh)); 15670598e1a2SLisandro Dalcin 1568698a79b9SLisandro Dalcin /* Read mesh format */ 15699566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 15709566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$MeshFormat", line)); 15719566063dSJacob Faibussowitsch PetscCall(GmshReadMeshFormat(gmsh)); 15729566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndMeshFormat", line)); 157311c56cb0SLisandro Dalcin 15748749820aSMatthew G. Knepley /* OPTIONAL Read mesh version (Neper only) */ 15759566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 15768749820aSMatthew G. Knepley PetscCall(GmshMatch(gmsh, "$MeshVersion", line, &match)); 15778749820aSMatthew G. Knepley if (match) { 15788749820aSMatthew G. Knepley PetscCall(GmshExpect(gmsh, "$MeshVersion", line)); 15798749820aSMatthew G. Knepley PetscCall(GmshReadMeshVersion(gmsh)); 15808749820aSMatthew G. Knepley PetscCall(GmshReadEndSection(gmsh, "$EndMeshVersion", line)); 15818749820aSMatthew G. Knepley /* Initial read for entity section */ 15828749820aSMatthew G. Knepley PetscCall(GmshReadSection(gmsh, line)); 15838749820aSMatthew G. Knepley } 15848749820aSMatthew G. Knepley 15858749820aSMatthew G. Knepley /* OPTIONAL Read mesh domain (Neper only) */ 15868749820aSMatthew G. Knepley PetscCall(GmshMatch(gmsh, "$Domain", line, &match)); 15878749820aSMatthew G. Knepley if (match) { 15888749820aSMatthew G. Knepley PetscCall(GmshExpect(gmsh, "$Domain", line)); 15898749820aSMatthew G. Knepley PetscCall(GmshReadMeshDomain(gmsh)); 15908749820aSMatthew G. Knepley PetscCall(GmshReadEndSection(gmsh, "$EndDomain", line)); 15918749820aSMatthew G. Knepley /* Initial read for entity section */ 15928749820aSMatthew G. Knepley PetscCall(GmshReadSection(gmsh, line)); 15938749820aSMatthew G. Knepley } 15948749820aSMatthew G. Knepley 15958749820aSMatthew G. Knepley /* OPTIONAL Read physical names */ 15969566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, "$PhysicalNames", line, &match)); 1597dc0ede3bSMatthew G. Knepley if (match) { 15989566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$PhysicalNames", line)); 15999566063dSJacob Faibussowitsch PetscCall(GmshReadPhysicalNames(gmsh, mesh)); 16009566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndPhysicalNames", line)); 1601698a79b9SLisandro Dalcin /* Initial read for entity section */ 16029566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 1603dc0ede3bSMatthew G. Knepley } 160411c56cb0SLisandro Dalcin 1605de78e4feSLisandro Dalcin /* Read entities */ 1606698a79b9SLisandro Dalcin if (gmsh->fileFormat >= 40) { 16079566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$Entities", line)); 16089566063dSJacob Faibussowitsch PetscCall(GmshReadEntities(gmsh, mesh)); 16099566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndEntities", line)); 1610698a79b9SLisandro Dalcin /* Initial read for nodes section */ 16119566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 1612de78e4feSLisandro Dalcin } 1613de78e4feSLisandro Dalcin 1614698a79b9SLisandro Dalcin /* Read nodes */ 16159566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$Nodes", line)); 16169566063dSJacob Faibussowitsch PetscCall(GmshReadNodes(gmsh, mesh)); 16179566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndNodes", line)); 161811c56cb0SLisandro Dalcin 1619698a79b9SLisandro Dalcin /* Read elements */ 16209566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 16219566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$Elements", line)); 16229566063dSJacob Faibussowitsch PetscCall(GmshReadElements(gmsh, mesh)); 16239566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndElements", line)); 1624de78e4feSLisandro Dalcin 16250598e1a2SLisandro Dalcin /* Read periodic section (OPTIONAL) */ 1626698a79b9SLisandro Dalcin if (periodic) { 16279566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 16289566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, "$Periodic", line, &periodic)); 1629ef12879bSLisandro Dalcin } 1630ef12879bSLisandro Dalcin if (periodic) { 16319566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$Periodic", line)); 16329566063dSJacob Faibussowitsch PetscCall(GmshReadPeriodic(gmsh, mesh)); 16339566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndPeriodic", line)); 1634698a79b9SLisandro Dalcin } 1635698a79b9SLisandro Dalcin 16369566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->wbuf)); 16379566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->sbuf)); 16389566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->nbuf)); 16390598e1a2SLisandro Dalcin 16400598e1a2SLisandro Dalcin dim = mesh->dim; 1641066ea43fSLisandro Dalcin order = mesh->order; 16420598e1a2SLisandro Dalcin numNodes = mesh->numNodes; 16430598e1a2SLisandro Dalcin numElems = mesh->numElems; 16440598e1a2SLisandro Dalcin numVerts = mesh->numVerts; 16450598e1a2SLisandro Dalcin numCells = mesh->numCells; 1646066ea43fSLisandro Dalcin 1647066ea43fSLisandro Dalcin { 1648066ea43fSLisandro Dalcin GmshElement *elemA = mesh->numCells > 0 ? mesh->elements : NULL; 16498e3a54c0SPierre Jolivet GmshElement *elemB = PetscSafePointerPlusOffset(elemA, mesh->numCells - 1); 1650066ea43fSLisandro Dalcin int ptA = elemA ? GmshCellMap[elemA->cellType].polytope : -1; 1651066ea43fSLisandro Dalcin int ptB = elemB ? GmshCellMap[elemB->cellType].polytope : -1; 1652066ea43fSLisandro Dalcin isSimplex = (ptA == GMSH_QUA || ptA == GMSH_HEX) ? PETSC_FALSE : PETSC_TRUE; 1653066ea43fSLisandro Dalcin isHybrid = (ptA == ptB) ? PETSC_FALSE : PETSC_TRUE; 1654066ea43fSLisandro Dalcin hasTetra = (ptA == GMSH_TET) ? PETSC_TRUE : PETSC_FALSE; 1655066ea43fSLisandro Dalcin } 1656698a79b9SLisandro Dalcin } 1657698a79b9SLisandro Dalcin 165848a46eb9SPierre Jolivet if (parentviewer) PetscCall(PetscViewerRestoreSubViewer(parentviewer, PETSC_COMM_SELF, &viewer)); 1659698a79b9SLisandro Dalcin 1660066ea43fSLisandro Dalcin { 1661066ea43fSLisandro Dalcin int buf[6]; 1662698a79b9SLisandro Dalcin 1663066ea43fSLisandro Dalcin buf[0] = (int)dim; 1664066ea43fSLisandro Dalcin buf[1] = (int)order; 1665066ea43fSLisandro Dalcin buf[2] = periodic; 1666066ea43fSLisandro Dalcin buf[3] = isSimplex; 1667066ea43fSLisandro Dalcin buf[4] = isHybrid; 1668066ea43fSLisandro Dalcin buf[5] = hasTetra; 1669066ea43fSLisandro Dalcin 16709566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(buf, 6, MPI_INT, 0, comm)); 1671066ea43fSLisandro Dalcin 1672066ea43fSLisandro Dalcin dim = buf[0]; 1673066ea43fSLisandro Dalcin order = buf[1]; 1674066ea43fSLisandro Dalcin periodic = buf[2] ? PETSC_TRUE : PETSC_FALSE; 1675066ea43fSLisandro Dalcin isSimplex = buf[3] ? PETSC_TRUE : PETSC_FALSE; 1676066ea43fSLisandro Dalcin isHybrid = buf[4] ? PETSC_TRUE : PETSC_FALSE; 1677066ea43fSLisandro Dalcin hasTetra = buf[5] ? PETSC_TRUE : PETSC_FALSE; 1678dea2a3c7SStefano Zampini } 1679dea2a3c7SStefano Zampini 1680066ea43fSLisandro Dalcin if (!highOrderSet) highOrder = (order > 1) ? PETSC_TRUE : PETSC_FALSE; 168108401ef6SPierre Jolivet PetscCheck(!highOrder || !isHybrid, comm, PETSC_ERR_SUP, "No support for discretization on hybrid meshes yet"); 1682066ea43fSLisandro Dalcin 16830598e1a2SLisandro Dalcin /* We do not want this label automatically computed, instead we fill it here */ 16849566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "celltype")); 168511c56cb0SLisandro Dalcin 1686a4bb7517SMichael Lange /* Allocate the cell-vertex mesh */ 16879566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(*dm, 0, numCells + numVerts)); 16880598e1a2SLisandro Dalcin for (cell = 0; cell < numCells; ++cell) { 16890598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + cell; 16900598e1a2SLisandro Dalcin DMPolytopeType ctype = DMPolytopeTypeFromGmsh(elem->cellType); 16910598e1a2SLisandro Dalcin if (hybrid && hasTetra && ctype == DM_POLYTOPE_TRI_PRISM) ctype = DM_POLYTOPE_TRI_PRISM_TENSOR; 16929566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(*dm, cell, elem->numVerts)); 16939566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(*dm, cell, ctype)); 1694db397164SMichael Lange } 169548a46eb9SPierre Jolivet for (v = numCells; v < numCells + numVerts; ++v) PetscCall(DMPlexSetCellType(*dm, v, DM_POLYTOPE_POINT)); 16969566063dSJacob Faibussowitsch PetscCall(DMSetUp(*dm)); 169796ca5757SLisandro Dalcin 1698a4bb7517SMichael Lange /* Add cell-vertex connections */ 16990598e1a2SLisandro Dalcin for (cell = 0; cell < numCells; ++cell) { 17000598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + cell; 17010598e1a2SLisandro Dalcin for (v = 0; v < elem->numVerts; ++v) { 17020598e1a2SLisandro Dalcin const PetscInt nn = elem->nodes[v]; 17030598e1a2SLisandro Dalcin const PetscInt vv = mesh->vertexMap[nn]; 17040598e1a2SLisandro Dalcin cone[v] = numCells + vv; 1705db397164SMichael Lange } 17069566063dSJacob Faibussowitsch PetscCall(DMPlexReorderCell(*dm, cell, cone)); 17079566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(*dm, cell, cone)); 1708a4bb7517SMichael Lange } 170996ca5757SLisandro Dalcin 17109566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 17119566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(*dm)); 17129566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(*dm)); 1713331830f3SMatthew G. Knepley if (interpolate) { 17145fd9971aSMatthew G. Knepley DM idm; 1715331830f3SMatthew G. Knepley 17169566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 17179566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 1718331830f3SMatthew G. Knepley *dm = idm; 1719331830f3SMatthew G. Knepley } 17209db5b827SMatthew G. Knepley PetscCall(DMPlexGetDepthStratum(*dm, 0, &vStart, &vEnd)); 1721917266a4SLisandro Dalcin 1722dd400576SPatrick Sanan if (rank == 0) { 1723a45dabc8SMatthew G. Knepley const PetscInt Nr = useregions ? mesh->numRegions : 0; 1724d1a54cefSMatthew G. Knepley 17259566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(Nr, ®ionSets)); 17260598e1a2SLisandro Dalcin for (cell = 0, e = 0; e < numElems; ++e) { 17270598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + e; 17286e1dd89aSLawrence Mitchell 17296e1dd89aSLawrence Mitchell /* Create cell sets */ 17300598e1a2SLisandro Dalcin if (elem->dim == dim && dim > 0) { 17310598e1a2SLisandro Dalcin if (elem->numTags > 0) { 1732df93260fSMatthew G. Knepley PetscInt Nt = elem->numTags, t, r; 1733a45dabc8SMatthew G. Knepley 1734df93260fSMatthew G. Knepley for (t = 0; t < Nt; ++t) { 1735df93260fSMatthew G. Knepley const PetscInt tag = elem->tags[t]; 17362b205333SMatthew G. Knepley const PetscBool generic = usegeneric && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE; 1737df93260fSMatthew G. Knepley 1738df93260fSMatthew G. Knepley if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &cellSets, "Cell Sets", cell, tag)); 1739a45dabc8SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 1740df93260fSMatthew G. Knepley if (mesh->regionDims[r] != dim) continue; 17419566063dSJacob Faibussowitsch if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], cell, tag)); 1742a45dabc8SMatthew G. Knepley } 17436e1dd89aSLawrence Mitchell } 1744df93260fSMatthew G. Knepley } 1745917266a4SLisandro Dalcin cell++; 17466e1dd89aSLawrence Mitchell } 17470c070f12SSander Arens 17480598e1a2SLisandro Dalcin /* Create face sets */ 1749aec57b10SMatthew G. Knepley if (elem->numTags && interpolate && elem->dim == dim - 1) { 17500598e1a2SLisandro Dalcin PetscInt joinSize; 17510598e1a2SLisandro Dalcin const PetscInt *join = NULL; 17520444adf6SMatthew G. Knepley PetscInt Nt = elem->numTags, pdepth; 1753a45dabc8SMatthew G. Knepley 17540598e1a2SLisandro Dalcin /* Find the relevant facet with vertex joins */ 17550598e1a2SLisandro Dalcin for (v = 0; v < elem->numVerts; ++v) { 17560598e1a2SLisandro Dalcin const PetscInt nn = elem->nodes[v]; 17570598e1a2SLisandro Dalcin const PetscInt vv = mesh->vertexMap[nn]; 17580598e1a2SLisandro Dalcin cone[v] = vStart + vv; 17590598e1a2SLisandro Dalcin } 17609566063dSJacob Faibussowitsch PetscCall(DMPlexGetFullJoin(*dm, elem->numVerts, cone, &joinSize, &join)); 176163a3b9bcSJacob 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); 17620444adf6SMatthew G. Knepley PetscCall(DMPlexGetPointDepth(*dm, join[0], &pdepth)); 17630444adf6SMatthew 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); 17640444adf6SMatthew G. Knepley for (PetscInt t = 0; t < Nt; ++t) { 17655ad74b4fSMatthew G. Knepley const PetscInt tag = elem->tags[t]; 17662b205333SMatthew G. Knepley const PetscBool generic = usegeneric && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE; 17675ad74b4fSMatthew G. Knepley 1768df93260fSMatthew G. Knepley if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &faceSets, "Face Sets", join[0], tag)); 17690444adf6SMatthew G. Knepley for (PetscInt r = 0; r < Nr; ++r) { 1770df93260fSMatthew G. Knepley if (mesh->regionDims[r] != dim - 1) continue; 17719566063dSJacob Faibussowitsch if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], join[0], tag)); 1772a45dabc8SMatthew G. Knepley } 17735ad74b4fSMatthew G. Knepley } 17749566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(*dm, elem->numVerts, cone, &joinSize, &join)); 17750598e1a2SLisandro Dalcin } 17760598e1a2SLisandro Dalcin 1777aec57b10SMatthew G. Knepley /* Create edge sets */ 1778aec57b10SMatthew G. Knepley if (elem->numTags && interpolate && dim > 2 && elem->dim == 1) { 1779aec57b10SMatthew G. Knepley PetscInt joinSize; 1780aec57b10SMatthew G. Knepley const PetscInt *join = NULL; 1781aec57b10SMatthew G. Knepley PetscInt Nt = elem->numTags, t, r; 1782aec57b10SMatthew G. Knepley 1783aec57b10SMatthew G. Knepley /* Find the relevant edge with vertex joins */ 1784aec57b10SMatthew G. Knepley for (v = 0; v < elem->numVerts; ++v) { 1785aec57b10SMatthew G. Knepley const PetscInt nn = elem->nodes[v]; 1786aec57b10SMatthew G. Knepley const PetscInt vv = mesh->vertexMap[nn]; 1787aec57b10SMatthew G. Knepley cone[v] = vStart + vv; 1788aec57b10SMatthew G. Knepley } 1789aec57b10SMatthew G. Knepley PetscCall(DMPlexGetJoin(*dm, elem->numVerts, cone, &joinSize, &join)); 1790aec57b10SMatthew 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); 1791aec57b10SMatthew G. Knepley for (t = 0; t < Nt; ++t) { 1792aec57b10SMatthew G. Knepley const PetscInt tag = elem->tags[t]; 17932b205333SMatthew G. Knepley const PetscBool generic = usegeneric && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE; 1794aec57b10SMatthew G. Knepley 17950444adf6SMatthew G. Knepley if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &edgeSets, "Edge Sets", join[0], tag)); 1796aec57b10SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 1797aec57b10SMatthew G. Knepley if (mesh->regionDims[r] != 1) continue; 1798aec57b10SMatthew G. Knepley if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], join[0], tag)); 1799aec57b10SMatthew G. Knepley } 1800aec57b10SMatthew G. Knepley } 1801aec57b10SMatthew G. Knepley PetscCall(DMPlexRestoreJoin(*dm, elem->numVerts, cone, &joinSize, &join)); 1802aec57b10SMatthew G. Knepley } 1803aec57b10SMatthew G. Knepley 18040c070f12SSander Arens /* Create vertex sets */ 1805aec57b10SMatthew G. Knepley if (elem->numTags && elem->dim == 0 && markvertices) { 18060598e1a2SLisandro Dalcin const PetscInt nn = elem->nodes[0]; 18070598e1a2SLisandro Dalcin const PetscInt vv = mesh->vertexMap[nn]; 1808a45dabc8SMatthew G. Knepley const PetscInt tag = elem->tags[0]; 1809a45dabc8SMatthew G. Knepley PetscInt r; 1810a45dabc8SMatthew G. Knepley 18118a3d9825SMatthew G. Knepley if (vv < 0) continue; 18122b205333SMatthew G. Knepley if (usegeneric) PetscCall(DMSetLabelValue_Fast(*dm, &vertSets, "Vertex Sets", vStart + vv, tag)); 181381a1af93SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 1814df93260fSMatthew G. Knepley if (mesh->regionDims[r] != 0) continue; 18159566063dSJacob Faibussowitsch if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], vStart + vv, tag)); 181681a1af93SMatthew G. Knepley } 181781a1af93SMatthew G. Knepley } 181881a1af93SMatthew G. Knepley } 181981a1af93SMatthew G. Knepley if (markvertices) { 182081a1af93SMatthew G. Knepley for (v = 0; v < numNodes; ++v) { 182181a1af93SMatthew G. Knepley const PetscInt vv = mesh->vertexMap[v]; 18227d5b9244SMatthew G. Knepley const PetscInt *tags = &mesh->nodelist->tag[v * GMSH_MAX_TAGS]; 18237d5b9244SMatthew G. Knepley PetscInt r, t; 182481a1af93SMatthew G. Knepley 18258a3d9825SMatthew G. Knepley if (vv < 0) continue; 18267d5b9244SMatthew G. Knepley for (t = 0; t < GMSH_MAX_TAGS; ++t) { 18277d5b9244SMatthew G. Knepley const PetscInt tag = tags[t]; 18282b205333SMatthew G. Knepley const PetscBool generic = usegeneric && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE; 18297d5b9244SMatthew G. Knepley 18307d5b9244SMatthew G. Knepley if (tag == -1) continue; 1831df93260fSMatthew G. Knepley if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &vertSets, "Vertex Sets", vStart + vv, tag)); 1832a45dabc8SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 18339566063dSJacob Faibussowitsch if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], vStart + vv, tag)); 18340598e1a2SLisandro Dalcin } 18350598e1a2SLisandro Dalcin } 18360598e1a2SLisandro Dalcin } 18370598e1a2SLisandro Dalcin } 18389566063dSJacob Faibussowitsch PetscCall(PetscFree(regionSets)); 1839a45dabc8SMatthew G. Knepley } 18400598e1a2SLisandro Dalcin 18410444adf6SMatthew G. Knepley { /* Create Cell/Face/Edge/Vertex Sets labels at all processes */ 18429371c9d4SSatish Balay enum { 18430444adf6SMatthew G. Knepley n = 5 18449371c9d4SSatish Balay }; 18457dd454faSLisandro Dalcin PetscBool flag[n]; 18467dd454faSLisandro Dalcin 18477dd454faSLisandro Dalcin flag[0] = cellSets ? PETSC_TRUE : PETSC_FALSE; 18487dd454faSLisandro Dalcin flag[1] = faceSets ? PETSC_TRUE : PETSC_FALSE; 18490444adf6SMatthew G. Knepley flag[2] = edgeSets ? PETSC_TRUE : PETSC_FALSE; 18500444adf6SMatthew G. Knepley flag[3] = vertSets ? PETSC_TRUE : PETSC_FALSE; 18510444adf6SMatthew G. Knepley flag[4] = marker ? PETSC_TRUE : PETSC_FALSE; 18529566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(flag, n, MPIU_BOOL, 0, comm)); 18539566063dSJacob Faibussowitsch if (flag[0]) PetscCall(DMCreateLabel(*dm, "Cell Sets")); 18549566063dSJacob Faibussowitsch if (flag[1]) PetscCall(DMCreateLabel(*dm, "Face Sets")); 18550444adf6SMatthew G. Knepley if (flag[2]) PetscCall(DMCreateLabel(*dm, "Edge Sets")); 18560444adf6SMatthew G. Knepley if (flag[3]) PetscCall(DMCreateLabel(*dm, "Vertex Sets")); 18570444adf6SMatthew G. Knepley if (flag[4]) PetscCall(DMCreateLabel(*dm, "marker")); 18587dd454faSLisandro Dalcin } 18597dd454faSLisandro Dalcin 18600598e1a2SLisandro Dalcin if (periodic) { 18619566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(numVerts, &periodicVerts)); 18620598e1a2SLisandro Dalcin for (n = 0; n < numNodes; ++n) { 18630598e1a2SLisandro Dalcin if (mesh->vertexMap[n] >= 0) { 18640598e1a2SLisandro Dalcin if (PetscUnlikely(mesh->periodMap[n] != n)) { 18650598e1a2SLisandro Dalcin PetscInt m = mesh->periodMap[n]; 18669566063dSJacob Faibussowitsch PetscCall(PetscBTSet(periodicVerts, mesh->vertexMap[n])); 18679566063dSJacob Faibussowitsch PetscCall(PetscBTSet(periodicVerts, mesh->vertexMap[m])); 18680598e1a2SLisandro Dalcin } 18690598e1a2SLisandro Dalcin } 18700598e1a2SLisandro Dalcin } 18719db5b827SMatthew G. Knepley PetscCall(DMGetCoordinateDM(*dm, &cdm)); 1872eae3dc7dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxHeight + 1, &periodicCells)); 18739db5b827SMatthew G. Knepley for (PetscInt h = 0; h <= maxHeight; ++h) { 18749db5b827SMatthew G. Knepley PetscInt pStart, pEnd; 18759db5b827SMatthew G. Knepley 18769db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(*dm, h, &pStart, &pEnd)); 18779db5b827SMatthew G. Knepley PetscCall(PetscBTCreate(pEnd - pStart, &periodicCells[h])); 18789db5b827SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 18799db5b827SMatthew G. Knepley PetscInt *closure = NULL; 18809db5b827SMatthew G. Knepley PetscInt Ncl; 18819db5b827SMatthew G. Knepley 18829db5b827SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure)); 18839db5b827SMatthew G. Knepley for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) { 18849db5b827SMatthew G. Knepley if (closure[cl] >= vStart && closure[cl] < vEnd) { 18859db5b827SMatthew G. Knepley if (PetscUnlikely(PetscBTLookup(periodicVerts, closure[cl] - vStart))) { 18869db5b827SMatthew G. Knepley PetscCall(PetscBTSet(periodicCells[h], p - pStart)); 18879371c9d4SSatish Balay break; 18880c070f12SSander Arens } 18890c070f12SSander Arens } 18900c070f12SSander Arens } 18919db5b827SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure)); 18929db5b827SMatthew G. Knepley } 18939db5b827SMatthew G. Knepley } 189416ad7e67SMichael Lange } 189516ad7e67SMichael Lange 1896066ea43fSLisandro Dalcin /* Setup coordinate DM */ 18970598e1a2SLisandro Dalcin if (coordDim < 0) coordDim = dim; 18989566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(*dm, coordDim)); 18999566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(*dm, &cdm)); 1900066ea43fSLisandro Dalcin if (highOrder) { 1901066ea43fSLisandro Dalcin PetscFE fe; 1902066ea43fSLisandro Dalcin PetscBool continuity = periodic ? PETSC_FALSE : PETSC_TRUE; 1903066ea43fSLisandro Dalcin PetscDTNodeType nodeType = PETSCDTNODES_EQUISPACED; 1904066ea43fSLisandro Dalcin 1905066ea43fSLisandro Dalcin if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */ 1906066ea43fSLisandro Dalcin 19079566063dSJacob Faibussowitsch PetscCall(GmshCreateFE(comm, NULL, isSimplex, continuity, nodeType, dim, coordDim, order, &fe)); 19089566063dSJacob Faibussowitsch PetscCall(PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_fe_view")); 19099566063dSJacob Faibussowitsch PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)fe)); 19109566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 19119566063dSJacob Faibussowitsch PetscCall(DMCreateDS(cdm)); 1912066ea43fSLisandro Dalcin } 19136858538eSMatthew G. Knepley if (periodic) { 19146858538eSMatthew G. Knepley PetscCall(DMClone(cdm, &cdmCell)); 19156858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(*dm, cdmCell)); 19166858538eSMatthew G. Knepley } 1917066ea43fSLisandro Dalcin 1918066ea43fSLisandro Dalcin /* Create coordinates */ 1919066ea43fSLisandro Dalcin if (highOrder) { 1920066ea43fSLisandro Dalcin PetscInt maxDof = GmshNumNodes_HEX(order) * coordDim; 1921066ea43fSLisandro Dalcin double *coords = mesh ? mesh->nodelist->xyz : NULL; 1922066ea43fSLisandro Dalcin PetscSection section; 1923066ea43fSLisandro Dalcin PetscScalar *cellCoords; 1924066ea43fSLisandro Dalcin 19259566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(cdm, NULL)); 19266858538eSMatthew G. Knepley PetscCall(DMGetLocalSection(cdm, &cs)); 19276858538eSMatthew G. Knepley PetscCall(PetscSectionClone(cs, §ion)); 19289566063dSJacob Faibussowitsch PetscCall(DMPlexSetClosurePermutationTensor(cdm, 0, section)); /* XXX Implement DMPlexSetClosurePermutationLexicographic() */ 1929066ea43fSLisandro Dalcin 19309566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(cdm, &coordinates)); 19319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof, &cellCoords)); 1932066ea43fSLisandro Dalcin for (cell = 0; cell < numCells; ++cell) { 1933066ea43fSLisandro Dalcin GmshElement *elem = mesh->elements + cell; 1934066ea43fSLisandro Dalcin const int *lexorder = GmshCellMap[elem->cellType].lexorder(); 1935b9bf55e5SMatthew G. Knepley int s = 0; 1936066ea43fSLisandro Dalcin for (n = 0; n < elem->numNodes; ++n) { 1937b9bf55e5SMatthew G. Knepley while (lexorder[n + s] < 0) ++s; 1938b9bf55e5SMatthew G. Knepley const PetscInt node = elem->nodes[lexorder[n + s]]; 1939b9bf55e5SMatthew G. Knepley for (d = 0; d < coordDim; ++d) cellCoords[(n + s) * coordDim + d] = (PetscReal)coords[node * 3 + d]; 1940b9bf55e5SMatthew G. Knepley } 1941b9bf55e5SMatthew G. Knepley if (s) { 1942b9bf55e5SMatthew G. Knepley /* For the coordinate mapping we weight vertices by -1/4 and edges by 1/2, which we get from Q_2 interpolation */ 1943b9bf55e5SMatthew G. Knepley PetscReal quaCenterWeights[9] = {-0.25, 0.5, -0.25, 0.5, 0.0, 0.5, -0.25, 0.5, -0.25}; 1944b9bf55e5SMatthew G. Knepley /* For the coordinate mapping we weight vertices by -1/4 and edges by 1/2, which we get from Q_2 interpolation */ 19459371c9d4SSatish 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}; 19469371c9d4SSatish 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}; 19479371c9d4SSatish 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}; 19489371c9d4SSatish 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}; 19499371c9d4SSatish 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}; 19509371c9d4SSatish 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}; 19519371c9d4SSatish 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}; 1952b9bf55e5SMatthew G. Knepley PetscReal *sdWeights2[9] = {NULL, NULL, NULL, NULL, quaCenterWeights, NULL, NULL, NULL, NULL}; 19539371c9d4SSatish Balay PetscReal *sdWeights3[27] = {NULL, NULL, NULL, NULL, hexBottomWeights, NULL, NULL, NULL, NULL, NULL, hexFrontWeights, NULL, hexLeftWeights, hexCenterWeights, hexRightWeights, NULL, hexBackWeights, NULL, 1954b9bf55e5SMatthew G. Knepley NULL, NULL, NULL, NULL, hexTopWeights, NULL, NULL, NULL, NULL}; 1955b9bf55e5SMatthew G. Knepley PetscReal **sdWeights[4] = {NULL, NULL, sdWeights2, sdWeights3}; 1956b9bf55e5SMatthew G. Knepley 1957b9bf55e5SMatthew G. Knepley /* Missing entries in serendipity cell, only works for 8-node quad and 20-node hex */ 1958b9bf55e5SMatthew G. Knepley for (n = 0; n < elem->numNodes + s; ++n) { 1959b9bf55e5SMatthew G. Knepley if (lexorder[n] >= 0) continue; 1960b9bf55e5SMatthew G. Knepley for (d = 0; d < coordDim; ++d) cellCoords[n * coordDim + d] = 0.0; 1961b9bf55e5SMatthew G. Knepley for (int bn = 0; bn < elem->numNodes + s; ++bn) { 1962b9bf55e5SMatthew G. Knepley if (lexorder[bn] < 0) continue; 1963b9bf55e5SMatthew G. Knepley const PetscReal *weights = sdWeights[coordDim][n]; 1964b9bf55e5SMatthew G. Knepley const PetscInt bnode = elem->nodes[lexorder[bn]]; 1965b9bf55e5SMatthew G. Knepley for (d = 0; d < coordDim; ++d) cellCoords[n * coordDim + d] += weights[bn] * (PetscReal)coords[bnode * 3 + d]; 1966b9bf55e5SMatthew G. Knepley } 1967b9bf55e5SMatthew G. Knepley } 1968066ea43fSLisandro Dalcin } 19699566063dSJacob Faibussowitsch PetscCall(DMPlexVecSetClosure(cdm, section, coordinates, cell, cellCoords, INSERT_VALUES)); 1970066ea43fSLisandro Dalcin } 19719566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 19729566063dSJacob Faibussowitsch PetscCall(PetscFree(cellCoords)); 1973066ea43fSLisandro Dalcin } else { 1974066ea43fSLisandro Dalcin PetscInt *nodeMap; 1975066ea43fSLisandro Dalcin double *coords = mesh ? mesh->nodelist->xyz : NULL; 1976066ea43fSLisandro Dalcin PetscScalar *pointCoords; 1977066ea43fSLisandro Dalcin 19786858538eSMatthew G. Knepley PetscCall(DMGetCoordinateSection(*dm, &cs)); 19796858538eSMatthew G. Knepley PetscCall(PetscSectionSetNumFields(cs, 1)); 19806858538eSMatthew G. Knepley PetscCall(PetscSectionSetFieldComponents(cs, 0, coordDim)); 19816858538eSMatthew G. Knepley PetscCall(PetscSectionSetChart(cs, numCells, numCells + numVerts)); 19826858538eSMatthew G. Knepley for (v = numCells; v < numCells + numVerts; ++v) { 19836858538eSMatthew G. Knepley PetscCall(PetscSectionSetDof(cs, v, coordDim)); 19846858538eSMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(cs, v, 0, coordDim)); 1985f45c9589SStefano Zampini } 19866858538eSMatthew G. Knepley PetscCall(PetscSectionSetUp(cs)); 19876858538eSMatthew G. Knepley 19886858538eSMatthew G. Knepley /* We need to localize coordinates on cells */ 19890598e1a2SLisandro Dalcin if (periodic) { 19909db5b827SMatthew G. Knepley PetscInt newStart = PETSC_MAX_INT, newEnd = -1, pStart, pEnd; 19919db5b827SMatthew G. Knepley 19926858538eSMatthew G. Knepley PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)cdmCell), &csCell)); 19936858538eSMatthew G. Knepley PetscCall(PetscSectionSetNumFields(csCell, 1)); 19946858538eSMatthew G. Knepley PetscCall(PetscSectionSetFieldComponents(csCell, 0, coordDim)); 19959db5b827SMatthew G. Knepley for (PetscInt h = 0; h <= maxHeight; h++) { 19969db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(cdmCell, h, &pStart, &pEnd)); 19979db5b827SMatthew G. Knepley newStart = PetscMin(newStart, pStart); 19989db5b827SMatthew G. Knepley newEnd = PetscMax(newEnd, pEnd); 19999db5b827SMatthew G. Knepley } 20009db5b827SMatthew G. Knepley PetscCall(PetscSectionSetChart(csCell, newStart, newEnd)); 20019db5b827SMatthew G. Knepley for (PetscInt h = 0; h <= maxHeight; h++) { 20029db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(cdmCell, h, &pStart, &pEnd)); 20039db5b827SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 20049db5b827SMatthew G. Knepley PetscInt *closure = NULL; 20059db5b827SMatthew G. Knepley PetscInt Ncl, Nv = 0; 20066858538eSMatthew G. Knepley 20079db5b827SMatthew G. Knepley if (PetscUnlikely(PetscBTLookup(periodicCells[h], p - pStart))) { 20089db5b827SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure)); 20099db5b827SMatthew G. Knepley for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) { 20109db5b827SMatthew G. Knepley if (closure[cl] >= vStart && closure[cl] < vEnd) ++Nv; 20119db5b827SMatthew G. Knepley } 20129db5b827SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure)); 20139db5b827SMatthew G. Knepley PetscCall(PetscSectionSetDof(csCell, p, Nv * coordDim)); 20149db5b827SMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(csCell, p, 0, Nv * coordDim)); 20159db5b827SMatthew G. Knepley } 2016f45c9589SStefano Zampini } 2017f45c9589SStefano Zampini } 20186858538eSMatthew G. Knepley PetscCall(PetscSectionSetUp(csCell)); 20196858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateSection(*dm, PETSC_DETERMINE, csCell)); 2020f45c9589SStefano Zampini } 2021066ea43fSLisandro Dalcin 20229566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(cdm, &coordinates)); 20239566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &pointCoords)); 20246858538eSMatthew G. Knepley PetscCall(PetscMalloc1(numVerts, &nodeMap)); 20256858538eSMatthew G. Knepley for (n = 0; n < numNodes; n++) 20266858538eSMatthew G. Knepley if (mesh->vertexMap[n] >= 0) nodeMap[mesh->vertexMap[n]] = n; 20276858538eSMatthew G. Knepley for (v = 0; v < numVerts; ++v) { 20286858538eSMatthew G. Knepley PetscInt off, node = nodeMap[v]; 20296858538eSMatthew G. Knepley 20306858538eSMatthew G. Knepley PetscCall(PetscSectionGetOffset(cs, numCells + v, &off)); 20316858538eSMatthew G. Knepley for (d = 0; d < coordDim; ++d) pointCoords[off + d] = (PetscReal)coords[node * 3 + d]; 20326858538eSMatthew G. Knepley } 20336858538eSMatthew G. Knepley PetscCall(VecRestoreArray(coordinates, &pointCoords)); 20346858538eSMatthew G. Knepley 20350598e1a2SLisandro Dalcin if (periodic) { 20369db5b827SMatthew G. Knepley PetscInt cStart, cEnd; 20379db5b827SMatthew G. Knepley 20389db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(cdmCell, 0, &cStart, &cEnd)); 20396858538eSMatthew G. Knepley PetscCall(DMCreateLocalVector(cdmCell, &coordinatesCell)); 20406858538eSMatthew G. Knepley PetscCall(VecGetArray(coordinatesCell, &pointCoords)); 20419db5b827SMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) { 20429db5b827SMatthew G. Knepley GmshElement *elem = mesh->elements + c - cStart; 20439db5b827SMatthew G. Knepley PetscInt *closure = NULL; 20449db5b827SMatthew G. Knepley PetscInt verts[8]; 20459db5b827SMatthew G. Knepley PetscInt Ncl, Nv = 0; 20469db5b827SMatthew G. Knepley 20479db5b827SMatthew G. Knepley for (PetscInt v = 0; v < elem->numVerts; ++v) cone[v] = elem->nodes[v]; 20489db5b827SMatthew G. Knepley PetscCall(DMPlexReorderCell(cdmCell, c, cone)); 20499db5b827SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(cdmCell, c, PETSC_TRUE, &Ncl, &closure)); 20509db5b827SMatthew G. Knepley for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) { 20519db5b827SMatthew G. Knepley if (closure[cl] >= vStart && closure[cl] < vEnd) verts[Nv++] = closure[cl]; 2052331830f3SMatthew G. Knepley } 20539db5b827SMatthew 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); 20549db5b827SMatthew G. Knepley for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) { 20559db5b827SMatthew G. Knepley const PetscInt point = closure[cl]; 20569db5b827SMatthew G. Knepley PetscInt hStart, h; 20579db5b827SMatthew G. Knepley 20589db5b827SMatthew G. Knepley PetscCall(DMPlexGetPointHeight(cdmCell, point, &h)); 20599db5b827SMatthew G. Knepley if (h > maxHeight) continue; 20609db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(cdmCell, h, &hStart, NULL)); 20619db5b827SMatthew G. Knepley if (PetscUnlikely(PetscBTLookup(periodicCells[h], point - hStart))) { 20629db5b827SMatthew G. Knepley PetscInt *pclosure = NULL; 20639db5b827SMatthew G. Knepley PetscInt Npcl, off, v; 20649db5b827SMatthew G. Knepley 20659db5b827SMatthew G. Knepley PetscCall(PetscSectionGetOffset(csCell, point, &off)); 20669db5b827SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(cdmCell, point, PETSC_TRUE, &Npcl, &pclosure)); 20679db5b827SMatthew G. Knepley for (PetscInt pcl = 0; pcl < Npcl * 2; pcl += 2) { 20689db5b827SMatthew G. Knepley if (pclosure[pcl] >= vStart && pclosure[pcl] < vEnd) { 20699db5b827SMatthew G. Knepley for (v = 0; v < Nv; ++v) 20709db5b827SMatthew G. Knepley if (verts[v] == pclosure[pcl]) break; 20719db5b827SMatthew 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); 20729db5b827SMatthew G. Knepley for (PetscInt d = 0; d < coordDim; ++d) pointCoords[off++] = (PetscReal)coords[cone[v] * 3 + d]; 20739db5b827SMatthew G. Knepley ++v; 20749db5b827SMatthew G. Knepley } 20759db5b827SMatthew G. Knepley } 20769db5b827SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(cdmCell, point, PETSC_TRUE, &Npcl, &pclosure)); 20779db5b827SMatthew G. Knepley } 20789db5b827SMatthew G. Knepley } 20799db5b827SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(cdmCell, c, PETSC_TRUE, &Ncl, &closure)); 2080331830f3SMatthew G. Knepley } 20816858538eSMatthew G. Knepley PetscCall(VecSetBlockSize(coordinatesCell, coordDim)); 20826858538eSMatthew G. Knepley PetscCall(VecRestoreArray(coordinatesCell, &pointCoords)); 20836858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(*dm, coordinatesCell)); 20846858538eSMatthew G. Knepley PetscCall(VecDestroy(&coordinatesCell)); 2085331830f3SMatthew G. Knepley } 20869db5b827SMatthew G. Knepley PetscCall(PetscFree(nodeMap)); 20876858538eSMatthew G. Knepley PetscCall(PetscSectionDestroy(&csCell)); 20886858538eSMatthew G. Knepley PetscCall(DMDestroy(&cdmCell)); 2089066ea43fSLisandro Dalcin } 2090066ea43fSLisandro Dalcin 20919566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 20929566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, coordDim)); 20939566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(*dm, coordinates)); 20949566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 209511c56cb0SLisandro Dalcin 20969566063dSJacob Faibussowitsch PetscCall(GmshMeshDestroy(&mesh)); 20979566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&periodicVerts)); 2098eae3dc7dSJacob Faibussowitsch if (periodic) { 2099eae3dc7dSJacob Faibussowitsch for (PetscInt h = 0; h <= maxHeight; ++h) PetscCall(PetscBTDestroy(periodicCells + h)); 2100eae3dc7dSJacob Faibussowitsch PetscCall(PetscFree(periodicCells)); 2101eae3dc7dSJacob Faibussowitsch } 210211c56cb0SLisandro Dalcin 2103066ea43fSLisandro Dalcin if (highOrder && project) { 2104066ea43fSLisandro Dalcin PetscFE fe; 2105066ea43fSLisandro Dalcin const char prefix[] = "dm_plex_gmsh_project_"; 2106066ea43fSLisandro Dalcin PetscBool continuity = periodic ? PETSC_FALSE : PETSC_TRUE; 2107066ea43fSLisandro Dalcin PetscDTNodeType nodeType = PETSCDTNODES_GAUSSJACOBI; 2108066ea43fSLisandro Dalcin 2109066ea43fSLisandro Dalcin if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */ 21109566063dSJacob Faibussowitsch PetscCall(GmshCreateFE(comm, prefix, isSimplex, continuity, nodeType, dim, coordDim, order, &fe)); 21119566063dSJacob Faibussowitsch PetscCall(PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_project_fe_view")); 2112e44f6aebSMatthew G. Knepley PetscCall(DMSetCoordinateDisc(*dm, fe, PETSC_TRUE)); 21139566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 2114066ea43fSLisandro Dalcin } 2115066ea43fSLisandro Dalcin 21169566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CreateGmsh, *dm, NULL, NULL, NULL)); 21173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2118331830f3SMatthew G. Knepley } 2119