1331830f3SMatthew G. Knepley #define PETSCDM_DLL 2af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 3730356f6SLisandro Dalcin #include <petsc/private/hashmapi.h> 4331830f3SMatthew G. Knepley 5066ea43fSLisandro Dalcin #include <../src/dm/impls/plex/gmshlex.h> 6066ea43fSLisandro Dalcin 7066ea43fSLisandro Dalcin #define GMSH_LEXORDER_ITEM(T, p) \ 8d71ae5a4SJacob Faibussowitsch static int *GmshLexOrder_##T##_##p(void) \ 9d71ae5a4SJacob Faibussowitsch { \ 10066ea43fSLisandro Dalcin static int Gmsh_LexOrder_##T##_##p[GmshNumNodes_##T(p)] = {-1}; \ 11066ea43fSLisandro Dalcin int *lex = Gmsh_LexOrder_##T##_##p; \ 12066ea43fSLisandro Dalcin if (lex[0] == -1) (void)GmshLexOrder_##T(p, lex, 0); \ 13066ea43fSLisandro Dalcin return lex; \ 14066ea43fSLisandro Dalcin } 15066ea43fSLisandro Dalcin 16d71ae5a4SJacob Faibussowitsch static int *GmshLexOrder_QUA_2_Serendipity(void) 17d71ae5a4SJacob Faibussowitsch { 18b9bf55e5SMatthew G. Knepley static int Gmsh_LexOrder_QUA_2_Serendipity[9] = {-1}; 19b9bf55e5SMatthew G. Knepley int *lex = Gmsh_LexOrder_QUA_2_Serendipity; 20b9bf55e5SMatthew G. Knepley if (lex[0] == -1) { 21b9bf55e5SMatthew G. Knepley /* Vertices */ 229371c9d4SSatish Balay lex[0] = 0; 239371c9d4SSatish Balay lex[2] = 1; 249371c9d4SSatish Balay lex[8] = 2; 259371c9d4SSatish Balay lex[6] = 3; 26b9bf55e5SMatthew G. Knepley /* Edges */ 279371c9d4SSatish Balay lex[1] = 4; 289371c9d4SSatish Balay lex[5] = 5; 299371c9d4SSatish Balay lex[7] = 6; 309371c9d4SSatish Balay lex[3] = 7; 31b9bf55e5SMatthew G. Knepley /* Cell */ 32b9bf55e5SMatthew G. Knepley lex[4] = -8; 33b9bf55e5SMatthew G. Knepley } 34b9bf55e5SMatthew G. Knepley return lex; 35b9bf55e5SMatthew G. Knepley } 36b9bf55e5SMatthew G. Knepley 37d71ae5a4SJacob Faibussowitsch static int *GmshLexOrder_HEX_2_Serendipity(void) 38d71ae5a4SJacob Faibussowitsch { 39b9bf55e5SMatthew G. Knepley static int Gmsh_LexOrder_HEX_2_Serendipity[27] = {-1}; 40b9bf55e5SMatthew G. Knepley int *lex = Gmsh_LexOrder_HEX_2_Serendipity; 41b9bf55e5SMatthew G. Knepley if (lex[0] == -1) { 42b9bf55e5SMatthew G. Knepley /* Vertices */ 439371c9d4SSatish Balay lex[0] = 0; 449371c9d4SSatish Balay lex[2] = 1; 459371c9d4SSatish Balay lex[8] = 2; 469371c9d4SSatish Balay lex[6] = 3; 479371c9d4SSatish Balay lex[18] = 4; 489371c9d4SSatish Balay lex[20] = 5; 499371c9d4SSatish Balay lex[26] = 6; 509371c9d4SSatish Balay lex[24] = 7; 51b9bf55e5SMatthew G. Knepley /* Edges */ 529371c9d4SSatish Balay lex[1] = 8; 539371c9d4SSatish Balay lex[3] = 9; 549371c9d4SSatish Balay lex[9] = 10; 559371c9d4SSatish Balay lex[5] = 11; 569371c9d4SSatish Balay lex[11] = 12; 579371c9d4SSatish Balay lex[7] = 13; 589371c9d4SSatish Balay lex[17] = 14; 599371c9d4SSatish Balay lex[15] = 15; 609371c9d4SSatish Balay lex[19] = 16; 619371c9d4SSatish Balay lex[21] = 17; 629371c9d4SSatish Balay lex[23] = 18; 639371c9d4SSatish Balay lex[25] = 19; 64b9bf55e5SMatthew G. Knepley /* Faces */ 659371c9d4SSatish Balay lex[4] = -20; 669371c9d4SSatish Balay lex[10] = -21; 679371c9d4SSatish Balay lex[12] = -22; 689371c9d4SSatish Balay lex[14] = -23; 699371c9d4SSatish Balay lex[16] = -24; 709371c9d4SSatish Balay lex[22] = -25; 71b9bf55e5SMatthew G. Knepley /* Cell */ 72b9bf55e5SMatthew G. Knepley lex[13] = -26; 73b9bf55e5SMatthew G. Knepley } 74b9bf55e5SMatthew G. Knepley return lex; 75b9bf55e5SMatthew G. Knepley } 76b9bf55e5SMatthew G. Knepley 77066ea43fSLisandro Dalcin #define GMSH_LEXORDER_LIST(T) \ 78066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 1) \ 79066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 2) \ 80066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 3) \ 81066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 4) \ 82066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 5) \ 83066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 6) \ 84066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 7) \ 85066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 8) \ 86066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 9) \ 87066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 10) 88066ea43fSLisandro Dalcin 89066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(VTX, 0) 90066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(SEG) 91066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(TRI) 92066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(QUA) 93066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(TET) 94066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(HEX) 95066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(PRI) 96066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(PYR) 97066ea43fSLisandro Dalcin 98066ea43fSLisandro Dalcin typedef enum { 99066ea43fSLisandro Dalcin GMSH_VTX = 0, 100066ea43fSLisandro Dalcin GMSH_SEG = 1, 101066ea43fSLisandro Dalcin GMSH_TRI = 2, 102066ea43fSLisandro Dalcin GMSH_QUA = 3, 103066ea43fSLisandro Dalcin GMSH_TET = 4, 104066ea43fSLisandro Dalcin GMSH_HEX = 5, 105066ea43fSLisandro Dalcin GMSH_PRI = 6, 106066ea43fSLisandro Dalcin GMSH_PYR = 7, 107066ea43fSLisandro Dalcin GMSH_NUM_POLYTOPES = 8 108066ea43fSLisandro Dalcin } GmshPolytopeType; 109066ea43fSLisandro Dalcin 110de78e4feSLisandro Dalcin typedef struct { 1110598e1a2SLisandro Dalcin int cellType; 112066ea43fSLisandro Dalcin int polytope; 1130598e1a2SLisandro Dalcin int dim; 1140598e1a2SLisandro Dalcin int order; 115066ea43fSLisandro Dalcin int numVerts; 1160598e1a2SLisandro Dalcin int numNodes; 117066ea43fSLisandro Dalcin int *(*lexorder)(void); 1180598e1a2SLisandro Dalcin } GmshCellInfo; 1190598e1a2SLisandro Dalcin 12010dd146fSPierre Jolivet #define GmshCellEntry(cellType, polytope, dim, order) {cellType, GMSH_##polytope, dim, order, GmshNumNodes_##polytope(1), GmshNumNodes_##polytope(order), GmshLexOrder_##polytope##_##order} 1210598e1a2SLisandro Dalcin 1220598e1a2SLisandro Dalcin static const GmshCellInfo GmshCellTable[] = { 123066ea43fSLisandro Dalcin GmshCellEntry(15, VTX, 0, 0), 1240598e1a2SLisandro Dalcin 1259371c9d4SSatish Balay GmshCellEntry(1, SEG, 1, 1), GmshCellEntry(8, SEG, 1, 2), GmshCellEntry(26, SEG, 1, 3), 1269371c9d4SSatish Balay GmshCellEntry(27, SEG, 1, 4), GmshCellEntry(28, SEG, 1, 5), GmshCellEntry(62, SEG, 1, 6), 1279371c9d4SSatish Balay GmshCellEntry(63, SEG, 1, 7), GmshCellEntry(64, SEG, 1, 8), GmshCellEntry(65, SEG, 1, 9), 128066ea43fSLisandro Dalcin GmshCellEntry(66, SEG, 1, 10), 1290598e1a2SLisandro Dalcin 1309371c9d4SSatish Balay GmshCellEntry(2, TRI, 2, 1), GmshCellEntry(9, TRI, 2, 2), GmshCellEntry(21, TRI, 2, 3), 1319371c9d4SSatish Balay GmshCellEntry(23, TRI, 2, 4), GmshCellEntry(25, TRI, 2, 5), GmshCellEntry(42, TRI, 2, 6), 1329371c9d4SSatish Balay GmshCellEntry(43, TRI, 2, 7), GmshCellEntry(44, TRI, 2, 8), GmshCellEntry(45, TRI, 2, 9), 133066ea43fSLisandro Dalcin GmshCellEntry(46, TRI, 2, 10), 1340598e1a2SLisandro Dalcin 1359371c9d4SSatish Balay GmshCellEntry(3, QUA, 2, 1), GmshCellEntry(10, QUA, 2, 2), {16, GMSH_QUA, 2, 2, 4, 8, GmshLexOrder_QUA_2_Serendipity}, 1369371c9d4SSatish Balay GmshCellEntry(36, QUA, 2, 3), GmshCellEntry(37, QUA, 2, 4), GmshCellEntry(38, QUA, 2, 5), 1379371c9d4SSatish Balay GmshCellEntry(47, QUA, 2, 6), GmshCellEntry(48, QUA, 2, 7), GmshCellEntry(49, QUA, 2, 8), 1389371c9d4SSatish Balay GmshCellEntry(50, QUA, 2, 9), GmshCellEntry(51, QUA, 2, 10), 1390598e1a2SLisandro Dalcin 1409371c9d4SSatish Balay GmshCellEntry(4, TET, 3, 1), GmshCellEntry(11, TET, 3, 2), GmshCellEntry(29, TET, 3, 3), 1419371c9d4SSatish Balay GmshCellEntry(30, TET, 3, 4), GmshCellEntry(31, TET, 3, 5), GmshCellEntry(71, TET, 3, 6), 1429371c9d4SSatish Balay GmshCellEntry(72, TET, 3, 7), GmshCellEntry(73, TET, 3, 8), GmshCellEntry(74, TET, 3, 9), 143066ea43fSLisandro Dalcin GmshCellEntry(75, TET, 3, 10), 1440598e1a2SLisandro Dalcin 1459371c9d4SSatish Balay GmshCellEntry(5, HEX, 3, 1), GmshCellEntry(12, HEX, 3, 2), {17, GMSH_HEX, 3, 2, 8, 20, GmshLexOrder_HEX_2_Serendipity}, 1469371c9d4SSatish Balay GmshCellEntry(92, HEX, 3, 3), GmshCellEntry(93, HEX, 3, 4), GmshCellEntry(94, HEX, 3, 5), 1479371c9d4SSatish Balay GmshCellEntry(95, HEX, 3, 6), GmshCellEntry(96, HEX, 3, 7), GmshCellEntry(97, HEX, 3, 8), 1489371c9d4SSatish Balay GmshCellEntry(98, HEX, 3, 9), GmshCellEntry(-1, HEX, 3, 10), 1490598e1a2SLisandro Dalcin 1509371c9d4SSatish Balay GmshCellEntry(6, PRI, 3, 1), GmshCellEntry(13, PRI, 3, 2), GmshCellEntry(90, PRI, 3, 3), 1519371c9d4SSatish Balay GmshCellEntry(91, PRI, 3, 4), GmshCellEntry(106, PRI, 3, 5), GmshCellEntry(107, PRI, 3, 6), 1529371c9d4SSatish Balay GmshCellEntry(108, PRI, 3, 7), GmshCellEntry(109, PRI, 3, 8), GmshCellEntry(110, PRI, 3, 9), 153066ea43fSLisandro Dalcin GmshCellEntry(-1, PRI, 3, 10), 1540598e1a2SLisandro Dalcin 1559371c9d4SSatish Balay GmshCellEntry(7, PYR, 3, 1), GmshCellEntry(14, PYR, 3, 2), GmshCellEntry(118, PYR, 3, 3), 1569371c9d4SSatish Balay GmshCellEntry(119, PYR, 3, 4), GmshCellEntry(120, PYR, 3, 5), GmshCellEntry(121, PYR, 3, 6), 1579371c9d4SSatish Balay GmshCellEntry(122, PYR, 3, 7), GmshCellEntry(123, PYR, 3, 8), GmshCellEntry(124, PYR, 3, 9), 158066ea43fSLisandro Dalcin GmshCellEntry(-1, PYR, 3, 10) 1590598e1a2SLisandro Dalcin 1600598e1a2SLisandro Dalcin #if 0 161066ea43fSLisandro Dalcin {20, GMSH_TRI, 2, 3, 3, 9, NULL}, 162066ea43fSLisandro Dalcin {18, GMSH_PRI, 3, 2, 6, 15, NULL}, 163066ea43fSLisandro Dalcin {19, GMSH_PYR, 3, 2, 5, 13, NULL}, 1640598e1a2SLisandro Dalcin #endif 1650598e1a2SLisandro Dalcin }; 1660598e1a2SLisandro Dalcin 1670598e1a2SLisandro Dalcin static GmshCellInfo GmshCellMap[150]; 1680598e1a2SLisandro Dalcin 169d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshCellInfoSetUp(void) 170d71ae5a4SJacob Faibussowitsch { 1710598e1a2SLisandro Dalcin size_t i, n; 1720598e1a2SLisandro Dalcin static PetscBool called = PETSC_FALSE; 1730598e1a2SLisandro Dalcin 1740598e1a2SLisandro Dalcin PetscFunctionBegin; 1754d86920dSPierre Jolivet if (called) PetscFunctionReturn(PETSC_SUCCESS); 1760598e1a2SLisandro Dalcin called = PETSC_TRUE; 177dd39110bSPierre Jolivet n = PETSC_STATIC_ARRAY_LENGTH(GmshCellMap); 1780598e1a2SLisandro Dalcin for (i = 0; i < n; ++i) { 1790598e1a2SLisandro Dalcin GmshCellMap[i].cellType = -1; 180066ea43fSLisandro Dalcin GmshCellMap[i].polytope = -1; 1810598e1a2SLisandro Dalcin } 182dd39110bSPierre Jolivet n = PETSC_STATIC_ARRAY_LENGTH(GmshCellTable); 183066ea43fSLisandro Dalcin for (i = 0; i < n; ++i) { 184066ea43fSLisandro Dalcin if (GmshCellTable[i].cellType <= 0) continue; 185066ea43fSLisandro Dalcin GmshCellMap[GmshCellTable[i].cellType] = GmshCellTable[i]; 186066ea43fSLisandro Dalcin } 1873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1880598e1a2SLisandro Dalcin } 1890598e1a2SLisandro Dalcin 1909371c9d4SSatish Balay #define GmshCellTypeCheck(ct) \ 1919371c9d4SSatish 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_); \ 1929371c9d4SSatish Balay PetscCheck(GmshCellMap[_ct_].polytope != -1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported Gmsh element type %d", _ct_);) 1930598e1a2SLisandro Dalcin 1940598e1a2SLisandro Dalcin typedef struct { 195698a79b9SLisandro Dalcin PetscViewer viewer; 196698a79b9SLisandro Dalcin int fileFormat; 197698a79b9SLisandro Dalcin int dataSize; 198698a79b9SLisandro Dalcin PetscBool binary; 199698a79b9SLisandro Dalcin PetscBool byteSwap; 200698a79b9SLisandro Dalcin size_t wlen; 201698a79b9SLisandro Dalcin void *wbuf; 202698a79b9SLisandro Dalcin size_t slen; 203698a79b9SLisandro Dalcin void *sbuf; 2040598e1a2SLisandro Dalcin PetscInt *nbuf; 2050598e1a2SLisandro Dalcin PetscInt nodeStart; 2060598e1a2SLisandro Dalcin PetscInt nodeEnd; 20733a088b6SMatthew G. Knepley PetscInt *nodeMap; 208698a79b9SLisandro Dalcin } GmshFile; 209de78e4feSLisandro Dalcin 2106497c311SBarry Smith /* 2116497c311SBarry Smith Returns an array of count items each with a sizeof(eltsize) 2126497c311SBarry Smith */ 2136497c311SBarry Smith static PetscErrorCode GmshBufferGet(GmshFile *gmsh, PetscCount count, size_t eltsize, void *buf) 214d71ae5a4SJacob Faibussowitsch { 215de78e4feSLisandro Dalcin size_t size = count * eltsize; 21611c56cb0SLisandro Dalcin 21711c56cb0SLisandro Dalcin PetscFunctionBegin; 218698a79b9SLisandro Dalcin if (gmsh->wlen < size) { 2199566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->wbuf)); 2209566063dSJacob Faibussowitsch PetscCall(PetscMalloc(size, &gmsh->wbuf)); 221698a79b9SLisandro Dalcin gmsh->wlen = size; 222de78e4feSLisandro Dalcin } 223698a79b9SLisandro Dalcin *(void **)buf = size ? gmsh->wbuf : NULL; 2243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 225de78e4feSLisandro Dalcin } 226de78e4feSLisandro Dalcin 2276497c311SBarry Smith /* 2286497c311SBarry Smith Returns an array of count items each with the size determined by the GmshFile 2296497c311SBarry Smith */ 2306497c311SBarry Smith static PetscErrorCode GmshBufferSizeGet(GmshFile *gmsh, PetscCount count, void *buf) 231d71ae5a4SJacob Faibussowitsch { 232698a79b9SLisandro Dalcin size_t dataSize = (size_t)gmsh->dataSize; 233698a79b9SLisandro Dalcin size_t size = count * dataSize; 234698a79b9SLisandro Dalcin 235698a79b9SLisandro Dalcin PetscFunctionBegin; 236698a79b9SLisandro Dalcin if (gmsh->slen < size) { 2379566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->sbuf)); 2389566063dSJacob Faibussowitsch PetscCall(PetscMalloc(size, &gmsh->sbuf)); 239698a79b9SLisandro Dalcin gmsh->slen = size; 240698a79b9SLisandro Dalcin } 241698a79b9SLisandro Dalcin *(void **)buf = size ? gmsh->sbuf : NULL; 2423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 243698a79b9SLisandro Dalcin } 244698a79b9SLisandro Dalcin 2456497c311SBarry Smith /* 2466497c311SBarry Smith Reads an array of count items each with the size determined by the PetscDataType 2476497c311SBarry Smith */ 2486497c311SBarry Smith static PetscErrorCode GmshRead(GmshFile *gmsh, void *buf, PetscCount count, PetscDataType dtype) 249d71ae5a4SJacob Faibussowitsch { 2506497c311SBarry Smith PetscInt icount; 2516497c311SBarry Smith 252de78e4feSLisandro Dalcin PetscFunctionBegin; 2536497c311SBarry Smith PetscCall(PetscIntCast(count, &icount)); 2546497c311SBarry Smith PetscCall(PetscViewerRead(gmsh->viewer, buf, icount, NULL, dtype)); 2556497c311SBarry Smith if (gmsh->byteSwap) PetscCall(PetscByteSwap(buf, dtype, icount)); 2563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 257698a79b9SLisandro Dalcin } 258698a79b9SLisandro Dalcin 2596497c311SBarry Smith static PetscErrorCode GmshReadString(GmshFile *gmsh, char *buf, PetscCount count) 260d71ae5a4SJacob Faibussowitsch { 2616497c311SBarry Smith PetscInt icount; 2626497c311SBarry Smith 263698a79b9SLisandro Dalcin PetscFunctionBegin; 2646497c311SBarry Smith PetscCall(PetscIntCast(count, &icount)); 2656497c311SBarry Smith PetscCall(PetscViewerRead(gmsh->viewer, buf, icount, NULL, PETSC_STRING)); 2663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 267698a79b9SLisandro Dalcin } 268698a79b9SLisandro Dalcin 269d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshMatch(PETSC_UNUSED GmshFile *gmsh, const char Section[], char line[PETSC_MAX_PATH_LEN], PetscBool *match) 270d71ae5a4SJacob Faibussowitsch { 271d6689ca9SLisandro Dalcin PetscFunctionBegin; 2729566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(line, Section, match)); 2733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 274d6689ca9SLisandro Dalcin } 275d6689ca9SLisandro Dalcin 276d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshExpect(GmshFile *gmsh, const char Section[], char line[PETSC_MAX_PATH_LEN]) 277d71ae5a4SJacob Faibussowitsch { 278d6689ca9SLisandro Dalcin PetscBool match; 279d6689ca9SLisandro Dalcin 280d6689ca9SLisandro Dalcin PetscFunctionBegin; 2819566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, Section, line, &match)); 28200045ab3SPierre Jolivet PetscCheck(match, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file, expecting %s, not %s", Section, line); 2833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 284d6689ca9SLisandro Dalcin } 285d6689ca9SLisandro Dalcin 286d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadSection(GmshFile *gmsh, char line[PETSC_MAX_PATH_LEN]) 287d71ae5a4SJacob Faibussowitsch { 288d6689ca9SLisandro Dalcin PetscBool match; 289d6689ca9SLisandro Dalcin 290d6689ca9SLisandro Dalcin PetscFunctionBegin; 291d6689ca9SLisandro Dalcin while (PETSC_TRUE) { 2929566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 1)); 2939566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, "$Comments", line, &match)); 294d6689ca9SLisandro Dalcin if (!match) break; 295d6689ca9SLisandro Dalcin while (PETSC_TRUE) { 2969566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 1)); 2979566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, "$EndComments", line, &match)); 298d6689ca9SLisandro Dalcin if (match) break; 299d6689ca9SLisandro Dalcin } 300d6689ca9SLisandro Dalcin } 3013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 302d6689ca9SLisandro Dalcin } 303d6689ca9SLisandro Dalcin 304d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEndSection(GmshFile *gmsh, const char EndSection[], char line[PETSC_MAX_PATH_LEN]) 305d71ae5a4SJacob Faibussowitsch { 306d6689ca9SLisandro Dalcin PetscFunctionBegin; 3079566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 1)); 3089566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, EndSection, line)); 3093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 310d6689ca9SLisandro Dalcin } 311d6689ca9SLisandro Dalcin 3126497c311SBarry Smith /* 3136497c311SBarry Smith Read into buf[] count number of PetscInt integers (the file storage size may be different than PetscInt) 3146497c311SBarry Smith */ 3156497c311SBarry Smith static PetscErrorCode GmshReadPetscInt(GmshFile *gmsh, PetscInt *buf, PetscCount count) 316d71ae5a4SJacob Faibussowitsch { 3176497c311SBarry Smith PetscCount i; 318698a79b9SLisandro Dalcin size_t dataSize = (size_t)gmsh->dataSize; 319698a79b9SLisandro Dalcin 320698a79b9SLisandro Dalcin PetscFunctionBegin; 321698a79b9SLisandro Dalcin if (dataSize == sizeof(PetscInt)) { 3229566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, buf, count, PETSC_INT)); 323698a79b9SLisandro Dalcin } else if (dataSize == sizeof(int)) { 324698a79b9SLisandro Dalcin int *ibuf = NULL; 3259566063dSJacob Faibussowitsch PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf)); 3269566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, ibuf, count, PETSC_ENUM)); 327698a79b9SLisandro Dalcin for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i]; 328698a79b9SLisandro Dalcin } else if (dataSize == sizeof(long)) { 329698a79b9SLisandro Dalcin long *ibuf = NULL; 3309566063dSJacob Faibussowitsch PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf)); 3319566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, ibuf, count, PETSC_LONG)); 332698a79b9SLisandro Dalcin for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i]; 333698a79b9SLisandro Dalcin } else if (dataSize == sizeof(PetscInt64)) { 334698a79b9SLisandro Dalcin PetscInt64 *ibuf = NULL; 3359566063dSJacob Faibussowitsch PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf)); 3369566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, ibuf, count, PETSC_INT64)); 337698a79b9SLisandro Dalcin for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i]; 338698a79b9SLisandro Dalcin } 3393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 340698a79b9SLisandro Dalcin } 341698a79b9SLisandro Dalcin 3426497c311SBarry Smith /* 3436497c311SBarry Smith Read into buf[] count number of PetscCount integers (the file storage size may be different than PetscCount) 3446497c311SBarry Smith */ 3456497c311SBarry Smith static PetscErrorCode GmshReadPetscCount(GmshFile *gmsh, PetscCount *buf, PetscCount count) 3466497c311SBarry Smith { 3476497c311SBarry Smith PetscCount i; 3486497c311SBarry Smith size_t dataSize = (size_t)gmsh->dataSize; 3496497c311SBarry Smith 3506497c311SBarry Smith PetscFunctionBegin; 3516497c311SBarry Smith if (dataSize == sizeof(PetscCount)) { 3526497c311SBarry Smith PetscCall(GmshRead(gmsh, buf, count, PETSC_COUNT)); 3536497c311SBarry Smith } else if (dataSize == sizeof(int)) { 3546497c311SBarry Smith int *ibuf = NULL; 3556497c311SBarry Smith PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf)); 3566497c311SBarry Smith PetscCall(GmshRead(gmsh, ibuf, count, PETSC_ENUM)); 3576497c311SBarry Smith for (i = 0; i < count; ++i) buf[i] = (PetscCount)ibuf[i]; 3586497c311SBarry Smith } else if (dataSize == sizeof(long)) { 3596497c311SBarry Smith long *ibuf = NULL; 3606497c311SBarry Smith PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf)); 3616497c311SBarry Smith PetscCall(GmshRead(gmsh, ibuf, count, PETSC_LONG)); 3626497c311SBarry Smith for (i = 0; i < count; ++i) buf[i] = (PetscCount)ibuf[i]; 3636497c311SBarry Smith } else if (dataSize == sizeof(PetscInt64)) { 3646497c311SBarry Smith PetscInt64 *ibuf = NULL; 3656497c311SBarry Smith PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf)); 3666497c311SBarry Smith PetscCall(GmshRead(gmsh, ibuf, count, PETSC_INT64)); 3676497c311SBarry Smith for (i = 0; i < count; ++i) buf[i] = (PetscCount)ibuf[i]; 3686497c311SBarry Smith } 3696497c311SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 3706497c311SBarry Smith } 3716497c311SBarry Smith 3726497c311SBarry Smith /* 3736497c311SBarry Smith Read into buf[] count number of PetscEnum integers 3746497c311SBarry Smith */ 3756497c311SBarry Smith static PetscErrorCode GmshReadInt(GmshFile *gmsh, int *buf, PetscCount count) 376d71ae5a4SJacob Faibussowitsch { 377698a79b9SLisandro Dalcin PetscFunctionBegin; 3789566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, buf, count, PETSC_ENUM)); 3793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 380698a79b9SLisandro Dalcin } 381698a79b9SLisandro Dalcin 3826497c311SBarry Smith /* 3836497c311SBarry Smith Read into buf[] count number of double 3846497c311SBarry Smith */ 3856497c311SBarry Smith static PetscErrorCode GmshReadDouble(GmshFile *gmsh, double *buf, PetscCount count) 386d71ae5a4SJacob Faibussowitsch { 387698a79b9SLisandro Dalcin PetscFunctionBegin; 3889566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, buf, count, PETSC_DOUBLE)); 3893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 390de78e4feSLisandro Dalcin } 391de78e4feSLisandro Dalcin 3929c0edc59SMatthew G. Knepley #define GMSH_MAX_TAGS 16 3937d5b9244SMatthew G. Knepley 394de78e4feSLisandro Dalcin typedef struct { 3950598e1a2SLisandro Dalcin PetscInt id; /* Entity ID */ 3960598e1a2SLisandro Dalcin PetscInt dim; /* Dimension */ 397de78e4feSLisandro Dalcin double bbox[6]; /* Bounding box */ 398de78e4feSLisandro Dalcin PetscInt numTags; /* Size of tag array */ 3997d5b9244SMatthew G. Knepley int tags[GMSH_MAX_TAGS]; /* Tag array */ 400de78e4feSLisandro Dalcin } GmshEntity; 401de78e4feSLisandro Dalcin 402de78e4feSLisandro Dalcin typedef struct { 403730356f6SLisandro Dalcin GmshEntity *entity[4]; 404730356f6SLisandro Dalcin PetscHMapI entityMap[4]; 405730356f6SLisandro Dalcin } GmshEntities; 406730356f6SLisandro Dalcin 4076497c311SBarry Smith static PetscErrorCode GmshEntitiesCreate(PetscCount count[4], GmshEntities **entities) 408d71ae5a4SJacob Faibussowitsch { 409730356f6SLisandro Dalcin PetscFunctionBegin; 4109566063dSJacob Faibussowitsch PetscCall(PetscNew(entities)); 4116497c311SBarry Smith for (PetscInt dim = 0; dim < 4; ++dim) { 4129566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(count[dim], &(*entities)->entity[dim])); 4139566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&(*entities)->entityMap[dim])); 414730356f6SLisandro Dalcin } 4153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 416730356f6SLisandro Dalcin } 417730356f6SLisandro Dalcin 418d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshEntitiesDestroy(GmshEntities **entities) 419d71ae5a4SJacob Faibussowitsch { 4200598e1a2SLisandro Dalcin PetscInt dim; 4210598e1a2SLisandro Dalcin 4220598e1a2SLisandro Dalcin PetscFunctionBegin; 4233ba16761SJacob Faibussowitsch if (!*entities) PetscFunctionReturn(PETSC_SUCCESS); 4240598e1a2SLisandro Dalcin for (dim = 0; dim < 4; ++dim) { 4259566063dSJacob Faibussowitsch PetscCall(PetscFree((*entities)->entity[dim])); 4269566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&(*entities)->entityMap[dim])); 4270598e1a2SLisandro Dalcin } 428f4f49eeaSPierre Jolivet PetscCall(PetscFree(*entities)); 4293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4300598e1a2SLisandro Dalcin } 4310598e1a2SLisandro Dalcin 432d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshEntitiesAdd(GmshEntities *entities, PetscInt index, PetscInt dim, PetscInt eid, GmshEntity **entity) 433d71ae5a4SJacob Faibussowitsch { 434730356f6SLisandro Dalcin PetscFunctionBegin; 4359566063dSJacob Faibussowitsch PetscCall(PetscHMapISet(entities->entityMap[dim], eid, index)); 436730356f6SLisandro Dalcin entities->entity[dim][index].dim = dim; 437730356f6SLisandro Dalcin entities->entity[dim][index].id = eid; 438730356f6SLisandro Dalcin if (entity) *entity = &entities->entity[dim][index]; 4393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 440730356f6SLisandro Dalcin } 441730356f6SLisandro Dalcin 442d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshEntitiesGet(GmshEntities *entities, PetscInt dim, PetscInt eid, GmshEntity **entity) 443d71ae5a4SJacob Faibussowitsch { 444730356f6SLisandro Dalcin PetscInt index; 445730356f6SLisandro Dalcin 446730356f6SLisandro Dalcin PetscFunctionBegin; 4479566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(entities->entityMap[dim], eid, &index)); 448730356f6SLisandro Dalcin *entity = &entities->entity[dim][index]; 4493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 450730356f6SLisandro Dalcin } 451730356f6SLisandro Dalcin 4520598e1a2SLisandro Dalcin typedef struct { 4530598e1a2SLisandro Dalcin PetscInt *id; /* Node IDs */ 4540598e1a2SLisandro Dalcin double *xyz; /* Coordinates */ 45581a1af93SMatthew G. Knepley PetscInt *tag; /* Physical tag */ 4560598e1a2SLisandro Dalcin } GmshNodes; 4570598e1a2SLisandro Dalcin 4586497c311SBarry Smith static PetscErrorCode GmshNodesCreate(PetscCount count, GmshNodes **nodes) 459d71ae5a4SJacob Faibussowitsch { 460730356f6SLisandro Dalcin PetscFunctionBegin; 4619566063dSJacob Faibussowitsch PetscCall(PetscNew(nodes)); 4629566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(count * 1, &(*nodes)->id)); 4639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(count * 3, &(*nodes)->xyz)); 4647d5b9244SMatthew G. Knepley PetscCall(PetscMalloc1(count * GMSH_MAX_TAGS, &(*nodes)->tag)); 4653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 466730356f6SLisandro Dalcin } 4670598e1a2SLisandro Dalcin 468d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshNodesDestroy(GmshNodes **nodes) 469d71ae5a4SJacob Faibussowitsch { 4700598e1a2SLisandro Dalcin PetscFunctionBegin; 4713ba16761SJacob Faibussowitsch if (!*nodes) PetscFunctionReturn(PETSC_SUCCESS); 4729566063dSJacob Faibussowitsch PetscCall(PetscFree((*nodes)->id)); 4739566063dSJacob Faibussowitsch PetscCall(PetscFree((*nodes)->xyz)); 4749566063dSJacob Faibussowitsch PetscCall(PetscFree((*nodes)->tag)); 475f4f49eeaSPierre Jolivet PetscCall(PetscFree(*nodes)); 4763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 477730356f6SLisandro Dalcin } 478730356f6SLisandro Dalcin 479730356f6SLisandro Dalcin typedef struct { 4800598e1a2SLisandro Dalcin PetscInt id; /* Element ID */ 4810598e1a2SLisandro Dalcin PetscInt dim; /* Dimension */ 482de78e4feSLisandro Dalcin PetscInt cellType; /* Cell type */ 4830598e1a2SLisandro Dalcin PetscInt numVerts; /* Size of vertex array */ 484de78e4feSLisandro Dalcin PetscInt numNodes; /* Size of node array */ 4850598e1a2SLisandro Dalcin PetscInt *nodes; /* Vertex/Node array */ 48681a1af93SMatthew G. Knepley PetscInt numTags; /* Size of physical tag array */ 4877d5b9244SMatthew G. Knepley int tags[GMSH_MAX_TAGS]; /* Physical tag array */ 488de78e4feSLisandro Dalcin } GmshElement; 489de78e4feSLisandro Dalcin 4906497c311SBarry Smith static PetscErrorCode GmshElementsCreate(PetscCount count, GmshElement **elements) 491d71ae5a4SJacob Faibussowitsch { 4920598e1a2SLisandro Dalcin PetscFunctionBegin; 4939566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(count, elements)); 4943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4950598e1a2SLisandro Dalcin } 4960598e1a2SLisandro Dalcin 497d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshElementsDestroy(GmshElement **elements) 498d71ae5a4SJacob Faibussowitsch { 4990598e1a2SLisandro Dalcin PetscFunctionBegin; 5003ba16761SJacob Faibussowitsch if (!*elements) PetscFunctionReturn(PETSC_SUCCESS); 5019566063dSJacob Faibussowitsch PetscCall(PetscFree(*elements)); 5023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5030598e1a2SLisandro Dalcin } 5040598e1a2SLisandro Dalcin 5050598e1a2SLisandro Dalcin typedef struct { 5060598e1a2SLisandro Dalcin PetscInt dim; 507066ea43fSLisandro Dalcin PetscInt order; 5080598e1a2SLisandro Dalcin GmshEntities *entities; 5090598e1a2SLisandro Dalcin PetscInt numNodes; 5100598e1a2SLisandro Dalcin GmshNodes *nodelist; 5110598e1a2SLisandro Dalcin PetscInt numElems; 5120598e1a2SLisandro Dalcin GmshElement *elements; 5130598e1a2SLisandro Dalcin PetscInt numVerts; 5140598e1a2SLisandro Dalcin PetscInt numCells; 5150598e1a2SLisandro Dalcin PetscInt *periodMap; 5160598e1a2SLisandro Dalcin PetscInt *vertexMap; 5170598e1a2SLisandro Dalcin PetscSegBuffer segbuf; 518a45dabc8SMatthew G. Knepley PetscInt numRegions; 51990d778b8SLisandro Dalcin PetscInt *regionDims; 520a45dabc8SMatthew G. Knepley PetscInt *regionTags; 521a45dabc8SMatthew G. Knepley char **regionNames; 5220598e1a2SLisandro Dalcin } GmshMesh; 5230598e1a2SLisandro Dalcin 524d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshMeshCreate(GmshMesh **mesh) 525d71ae5a4SJacob Faibussowitsch { 5260598e1a2SLisandro Dalcin PetscFunctionBegin; 5279566063dSJacob Faibussowitsch PetscCall(PetscNew(mesh)); 5289566063dSJacob Faibussowitsch PetscCall(PetscSegBufferCreate(sizeof(PetscInt), 0, &(*mesh)->segbuf)); 5293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5300598e1a2SLisandro Dalcin } 5310598e1a2SLisandro Dalcin 532d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshMeshDestroy(GmshMesh **mesh) 533d71ae5a4SJacob Faibussowitsch { 534a45dabc8SMatthew G. Knepley PetscInt r; 5350598e1a2SLisandro Dalcin 5360598e1a2SLisandro Dalcin PetscFunctionBegin; 5373ba16761SJacob Faibussowitsch if (!*mesh) PetscFunctionReturn(PETSC_SUCCESS); 5389566063dSJacob Faibussowitsch PetscCall(GmshEntitiesDestroy(&(*mesh)->entities)); 5399566063dSJacob Faibussowitsch PetscCall(GmshNodesDestroy(&(*mesh)->nodelist)); 5409566063dSJacob Faibussowitsch PetscCall(GmshElementsDestroy(&(*mesh)->elements)); 5419566063dSJacob Faibussowitsch PetscCall(PetscFree((*mesh)->periodMap)); 5429566063dSJacob Faibussowitsch PetscCall(PetscFree((*mesh)->vertexMap)); 5439566063dSJacob Faibussowitsch PetscCall(PetscSegBufferDestroy(&(*mesh)->segbuf)); 5449566063dSJacob Faibussowitsch for (r = 0; r < (*mesh)->numRegions; ++r) PetscCall(PetscFree((*mesh)->regionNames[r])); 54590d778b8SLisandro Dalcin PetscCall(PetscFree3((*mesh)->regionDims, (*mesh)->regionTags, (*mesh)->regionNames)); 546f4f49eeaSPierre Jolivet PetscCall(PetscFree(*mesh)); 5473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5480598e1a2SLisandro Dalcin } 5490598e1a2SLisandro Dalcin 550d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes_v22(GmshFile *gmsh, GmshMesh *mesh) 551d71ae5a4SJacob Faibussowitsch { 552698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 553698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 554de78e4feSLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 5557d5b9244SMatthew G. Knepley int n, t, num, nid, snum; 5560598e1a2SLisandro Dalcin GmshNodes *nodes; 557de78e4feSLisandro Dalcin 558de78e4feSLisandro Dalcin PetscFunctionBegin; 5599566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 560698a79b9SLisandro Dalcin snum = sscanf(line, "%d", &num); 56108401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 5629566063dSJacob Faibussowitsch PetscCall(GmshNodesCreate(num, &nodes)); 5630598e1a2SLisandro Dalcin mesh->numNodes = num; 5640598e1a2SLisandro Dalcin mesh->nodelist = nodes; 5650598e1a2SLisandro Dalcin for (n = 0; n < num; ++n) { 5660598e1a2SLisandro Dalcin double *xyz = nodes->xyz + n * 3; 5679566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM)); 5689566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE)); 5699566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nid, PETSC_ENUM, 1)); 5709566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(xyz, PETSC_DOUBLE, 3)); 5710598e1a2SLisandro Dalcin nodes->id[n] = nid; 5727d5b9244SMatthew G. Knepley for (t = 0; t < GMSH_MAX_TAGS; ++t) nodes->tag[n * GMSH_MAX_TAGS + t] = -1; 57311c56cb0SLisandro Dalcin } 5743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 57511c56cb0SLisandro Dalcin } 57611c56cb0SLisandro Dalcin 577de78e4feSLisandro Dalcin /* Gmsh elements can be of any dimension/co-dimension, so we need to traverse the 578de78e4feSLisandro Dalcin file contents multiple times to figure out the true number of cells and facets 579de78e4feSLisandro Dalcin in the given mesh. To make this more efficient we read the file contents only 580de78e4feSLisandro Dalcin once and store them in memory, while determining the true number of cells. */ 581d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements_v22(GmshFile *gmsh, GmshMesh *mesh) 582d71ae5a4SJacob Faibussowitsch { 583698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 584698a79b9SLisandro Dalcin PetscBool binary = gmsh->binary; 585698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 586de78e4feSLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 5870598e1a2SLisandro Dalcin int i, c, p, num, ibuf[1 + 4 + 1000], snum; 5880598e1a2SLisandro Dalcin int cellType, numElem, numVerts, numNodes, numTags; 589df032b82SMatthew G. Knepley GmshElement *elements; 5900598e1a2SLisandro Dalcin PetscInt *nodeMap = gmsh->nodeMap; 591df032b82SMatthew G. Knepley 592df032b82SMatthew G. Knepley PetscFunctionBegin; 5939566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 594698a79b9SLisandro Dalcin snum = sscanf(line, "%d", &num); 59508401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 5969566063dSJacob Faibussowitsch PetscCall(GmshElementsCreate(num, &elements)); 5970598e1a2SLisandro Dalcin mesh->numElems = num; 5980598e1a2SLisandro Dalcin mesh->elements = elements; 599698a79b9SLisandro Dalcin for (c = 0; c < num;) { 6009566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM)); 6019566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, 3)); 6020598e1a2SLisandro Dalcin 6030598e1a2SLisandro Dalcin cellType = binary ? ibuf[0] : ibuf[1]; 6040598e1a2SLisandro Dalcin numElem = binary ? ibuf[1] : 1; 605df032b82SMatthew G. Knepley numTags = ibuf[2]; 6060598e1a2SLisandro Dalcin 6079566063dSJacob Faibussowitsch PetscCall(GmshCellTypeCheck(cellType)); 6080598e1a2SLisandro Dalcin numVerts = GmshCellMap[cellType].numVerts; 6090598e1a2SLisandro Dalcin numNodes = GmshCellMap[cellType].numNodes; 6100598e1a2SLisandro Dalcin 611df032b82SMatthew G. Knepley for (i = 0; i < numElem; ++i, ++c) { 6120598e1a2SLisandro Dalcin GmshElement *element = elements + c; 6130598e1a2SLisandro Dalcin const int off = binary ? 0 : 1, nint = 1 + numTags + numNodes - off; 6140598e1a2SLisandro Dalcin const int *id = ibuf, *nodes = ibuf + 1 + numTags, *tags = ibuf + 1; 6159566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf + off, nint, NULL, PETSC_ENUM)); 6169566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf + off, PETSC_ENUM, nint)); 6170598e1a2SLisandro Dalcin element->id = id[0]; 6180598e1a2SLisandro Dalcin element->dim = GmshCellMap[cellType].dim; 6190598e1a2SLisandro Dalcin element->cellType = cellType; 6200598e1a2SLisandro Dalcin element->numVerts = numVerts; 6210598e1a2SLisandro Dalcin element->numNodes = numNodes; 6227d5b9244SMatthew G. Knepley element->numTags = PetscMin(numTags, GMSH_MAX_TAGS); 6239566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes)); 6240598e1a2SLisandro Dalcin for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]]; 6250598e1a2SLisandro Dalcin for (p = 0; p < element->numTags; p++) element->tags[p] = tags[p]; 626df032b82SMatthew G. Knepley } 627df032b82SMatthew G. Knepley } 6283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 629df032b82SMatthew G. Knepley } 6307d282ae0SMichael Lange 631de78e4feSLisandro Dalcin /* 632de78e4feSLisandro Dalcin $Entities 633de78e4feSLisandro Dalcin numPoints(unsigned long) numCurves(unsigned long) 634de78e4feSLisandro Dalcin numSurfaces(unsigned long) numVolumes(unsigned long) 635de78e4feSLisandro Dalcin // points 636de78e4feSLisandro Dalcin tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 637de78e4feSLisandro Dalcin boxMaxX(double) boxMaxY(double) boxMaxZ(double) 638de78e4feSLisandro Dalcin numPhysicals(unsigned long) phyisicalTag[...](int) 639de78e4feSLisandro Dalcin ... 640de78e4feSLisandro Dalcin // curves 641de78e4feSLisandro Dalcin tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 642de78e4feSLisandro Dalcin boxMaxX(double) boxMaxY(double) boxMaxZ(double) 643de78e4feSLisandro Dalcin numPhysicals(unsigned long) physicalTag[...](int) 644de78e4feSLisandro Dalcin numBREPVert(unsigned long) tagBREPVert[...](int) 645de78e4feSLisandro Dalcin ... 646de78e4feSLisandro Dalcin // surfaces 647de78e4feSLisandro Dalcin tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 648de78e4feSLisandro Dalcin boxMaxX(double) boxMaxY(double) boxMaxZ(double) 649de78e4feSLisandro Dalcin numPhysicals(unsigned long) physicalTag[...](int) 650de78e4feSLisandro Dalcin numBREPCurve(unsigned long) tagBREPCurve[...](int) 651de78e4feSLisandro Dalcin ... 652de78e4feSLisandro Dalcin // volumes 653de78e4feSLisandro Dalcin tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 654de78e4feSLisandro Dalcin boxMaxX(double) boxMaxY(double) boxMaxZ(double) 655de78e4feSLisandro Dalcin numPhysicals(unsigned long) physicalTag[...](int) 656de78e4feSLisandro Dalcin numBREPSurfaces(unsigned long) tagBREPSurfaces[...](int) 657de78e4feSLisandro Dalcin ... 658de78e4feSLisandro Dalcin $EndEntities 659de78e4feSLisandro Dalcin */ 660d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEntities_v40(GmshFile *gmsh, GmshMesh *mesh) 661d71ae5a4SJacob Faibussowitsch { 662698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 663698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 6646497c311SBarry Smith long lnum, lbuf[4]; 665730356f6SLisandro Dalcin int dim, eid, numTags, *ibuf, t; 6666497c311SBarry Smith PetscCount index, count[4]; 6676497c311SBarry Smith PetscInt i, num; 668a5ba3d71SLisandro Dalcin GmshEntity *entity = NULL; 669de78e4feSLisandro Dalcin 670de78e4feSLisandro Dalcin PetscFunctionBegin; 6719566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, lbuf, 4, NULL, PETSC_LONG)); 6729566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(lbuf, PETSC_LONG, 4)); 6736497c311SBarry Smith for (i = 0; i < 4; ++i) count[i] = (PetscCount)lbuf[i]; 6749566063dSJacob Faibussowitsch PetscCall(GmshEntitiesCreate(count, &mesh->entities)); 675de78e4feSLisandro Dalcin for (dim = 0; dim < 4; ++dim) { 676730356f6SLisandro Dalcin for (index = 0; index < count[dim]; ++index) { 6779566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &eid, 1, NULL, PETSC_ENUM)); 6789566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&eid, PETSC_ENUM, 1)); 6799566063dSJacob Faibussowitsch PetscCall(GmshEntitiesAdd(mesh->entities, (PetscInt)index, dim, eid, &entity)); 6809566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, entity->bbox, 6, NULL, PETSC_DOUBLE)); 6819566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(entity->bbox, PETSC_DOUBLE, 6)); 6826497c311SBarry Smith PetscCall(PetscViewerRead(viewer, &lnum, 1, NULL, PETSC_LONG)); 6836497c311SBarry Smith if (byteSwap) PetscCall(PetscByteSwap(&lnum, PETSC_LONG, 1)); 6846497c311SBarry Smith PetscCall(PetscIntCast(lnum, &num)); 6859566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, num, sizeof(int), &ibuf)); 6869566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, num, NULL, PETSC_ENUM)); 6879566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, num)); 6887d5b9244SMatthew G. Knepley entity->numTags = numTags = (int)PetscMin(num, GMSH_MAX_TAGS); 689de78e4feSLisandro Dalcin for (t = 0; t < numTags; ++t) entity->tags[t] = ibuf[t]; 690de78e4feSLisandro Dalcin if (dim == 0) continue; 6916497c311SBarry Smith PetscCall(PetscViewerRead(viewer, &lnum, 1, NULL, PETSC_LONG)); 6926497c311SBarry Smith if (byteSwap) PetscCall(PetscByteSwap(&lnum, PETSC_LONG, 1)); 6936497c311SBarry Smith PetscCall(GmshBufferGet(gmsh, lnum, sizeof(int), &ibuf)); 6946497c311SBarry Smith PetscCall(PetscIntCast(lnum, &num)); 6959566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, num, NULL, PETSC_ENUM)); 6969566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, num)); 697de78e4feSLisandro Dalcin } 698de78e4feSLisandro Dalcin } 6993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 700de78e4feSLisandro Dalcin } 701de78e4feSLisandro Dalcin 702de78e4feSLisandro Dalcin /* 703de78e4feSLisandro Dalcin $Nodes 704de78e4feSLisandro Dalcin numEntityBlocks(unsigned long) numNodes(unsigned long) 705de78e4feSLisandro Dalcin tagEntity(int) dimEntity(int) typeNode(int) numNodes(unsigned long) 706de78e4feSLisandro Dalcin tag(int) x(double) y(double) z(double) 707de78e4feSLisandro Dalcin ... 708de78e4feSLisandro Dalcin ... 709de78e4feSLisandro Dalcin $EndNodes 710de78e4feSLisandro Dalcin */ 711d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes_v40(GmshFile *gmsh, GmshMesh *mesh) 712d71ae5a4SJacob Faibussowitsch { 713698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 714698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 7157d5b9244SMatthew G. Knepley long block, node, n, t, numEntityBlocks, numTotalNodes, numNodes; 716de78e4feSLisandro Dalcin int info[3], nid; 7170598e1a2SLisandro Dalcin GmshNodes *nodes; 718de78e4feSLisandro Dalcin 719de78e4feSLisandro Dalcin PetscFunctionBegin; 7209566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numEntityBlocks, 1, NULL, PETSC_LONG)); 7219566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numEntityBlocks, PETSC_LONG, 1)); 7229566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numTotalNodes, 1, NULL, PETSC_LONG)); 7239566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numTotalNodes, PETSC_LONG, 1)); 7249566063dSJacob Faibussowitsch PetscCall(GmshNodesCreate(numTotalNodes, &nodes)); 7256497c311SBarry Smith PetscCall(PetscIntCast(numTotalNodes, &mesh->numNodes)); 7260598e1a2SLisandro Dalcin mesh->nodelist = nodes; 7270598e1a2SLisandro Dalcin for (n = 0, block = 0; block < numEntityBlocks; ++block) { 7289566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, info, 3, NULL, PETSC_ENUM)); 7299566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numNodes, 1, NULL, PETSC_LONG)); 7309566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numNodes, PETSC_LONG, 1)); 731698a79b9SLisandro Dalcin if (gmsh->binary) { 732277f51e8SBarry Smith size_t nbytes = sizeof(int) + 3 * sizeof(double); 733da81f932SPierre Jolivet char *cbuf = NULL; /* dummy value to prevent warning from compiler about possible uninitialized value */ 7346497c311SBarry Smith PetscInt icnt; 7356497c311SBarry Smith 7369566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, numNodes, nbytes, &cbuf)); 7376497c311SBarry Smith PetscCall(PetscIntCast(numNodes * nbytes, &icnt)); 7386497c311SBarry Smith PetscCall(PetscViewerRead(viewer, cbuf, icnt, NULL, PETSC_CHAR)); 7390598e1a2SLisandro Dalcin for (node = 0; node < numNodes; ++node, ++n) { 740de78e4feSLisandro Dalcin char *cnid = cbuf + node * nbytes, *cxyz = cnid + sizeof(int); 7410598e1a2SLisandro Dalcin double *xyz = nodes->xyz + n * 3; 7426497c311SBarry Smith 7439566063dSJacob Faibussowitsch if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(cnid, PETSC_ENUM, 1)); 7449566063dSJacob Faibussowitsch if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(cxyz, PETSC_DOUBLE, 3)); 7459566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(&nid, cnid, sizeof(int))); 7469566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(xyz, cxyz, 3 * sizeof(double))); 7479566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nid, PETSC_ENUM, 1)); 7489566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(xyz, PETSC_DOUBLE, 3)); 7490598e1a2SLisandro Dalcin nodes->id[n] = nid; 7507d5b9244SMatthew G. Knepley for (t = 0; t < GMSH_MAX_TAGS; ++t) nodes->tag[n * GMSH_MAX_TAGS + t] = -1; 751de78e4feSLisandro Dalcin } 752de78e4feSLisandro Dalcin } else { 7530598e1a2SLisandro Dalcin for (node = 0; node < numNodes; ++node, ++n) { 7540598e1a2SLisandro Dalcin double *xyz = nodes->xyz + n * 3; 7556497c311SBarry Smith 7569566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM)); 7579566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE)); 7589566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nid, PETSC_ENUM, 1)); 7599566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(xyz, PETSC_DOUBLE, 3)); 7600598e1a2SLisandro Dalcin nodes->id[n] = nid; 7617d5b9244SMatthew G. Knepley for (t = 0; t < GMSH_MAX_TAGS; ++t) nodes->tag[n * GMSH_MAX_TAGS + t] = -1; 762de78e4feSLisandro Dalcin } 763de78e4feSLisandro Dalcin } 764de78e4feSLisandro Dalcin } 7653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 766de78e4feSLisandro Dalcin } 767de78e4feSLisandro Dalcin 768de78e4feSLisandro Dalcin /* 769de78e4feSLisandro Dalcin $Elements 770de78e4feSLisandro Dalcin numEntityBlocks(unsigned long) numElements(unsigned long) 771de78e4feSLisandro Dalcin tagEntity(int) dimEntity(int) typeEle(int) numElements(unsigned long) 772de78e4feSLisandro Dalcin tag(int) numVert[...](int) 773de78e4feSLisandro Dalcin ... 774de78e4feSLisandro Dalcin ... 775de78e4feSLisandro Dalcin $EndElements 776de78e4feSLisandro Dalcin */ 777d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements_v40(GmshFile *gmsh, GmshMesh *mesh) 778d71ae5a4SJacob Faibussowitsch { 779698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 780698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 781de78e4feSLisandro Dalcin long c, block, numEntityBlocks, numTotalElements, elem, numElements; 782de78e4feSLisandro Dalcin int p, info[3], *ibuf = NULL; 7830598e1a2SLisandro Dalcin int eid, dim, cellType, numVerts, numNodes, numTags; 784a5ba3d71SLisandro Dalcin GmshEntity *entity = NULL; 785de78e4feSLisandro Dalcin GmshElement *elements; 7866497c311SBarry Smith PetscInt *nodeMap = gmsh->nodeMap, icnt; 787de78e4feSLisandro Dalcin 788de78e4feSLisandro Dalcin PetscFunctionBegin; 7899566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numEntityBlocks, 1, NULL, PETSC_LONG)); 7909566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numEntityBlocks, PETSC_LONG, 1)); 7919566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numTotalElements, 1, NULL, PETSC_LONG)); 7929566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numTotalElements, PETSC_LONG, 1)); 7939566063dSJacob Faibussowitsch PetscCall(GmshElementsCreate(numTotalElements, &elements)); 7946497c311SBarry Smith PetscCall(PetscIntCast(numTotalElements, &mesh->numElems)); 7950598e1a2SLisandro Dalcin mesh->elements = elements; 796de78e4feSLisandro Dalcin for (c = 0, block = 0; block < numEntityBlocks; ++block) { 7979566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, info, 3, NULL, PETSC_ENUM)); 7989566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(info, PETSC_ENUM, 3)); 7999371c9d4SSatish Balay eid = info[0]; 8009371c9d4SSatish Balay dim = info[1]; 8019371c9d4SSatish Balay cellType = info[2]; 8029566063dSJacob Faibussowitsch PetscCall(GmshEntitiesGet(mesh->entities, dim, eid, &entity)); 8039566063dSJacob Faibussowitsch PetscCall(GmshCellTypeCheck(cellType)); 8040598e1a2SLisandro Dalcin numVerts = GmshCellMap[cellType].numVerts; 8050598e1a2SLisandro Dalcin numNodes = GmshCellMap[cellType].numNodes; 8066497c311SBarry Smith numTags = (int)entity->numTags; 8079566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numElements, 1, NULL, PETSC_LONG)); 8089566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numElements, PETSC_LONG, 1)); 8099566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, (1 + numNodes) * numElements, sizeof(int), &ibuf)); 8106497c311SBarry Smith PetscCall(PetscIntCast((1 + numNodes) * numElements, &icnt)); 8116497c311SBarry Smith PetscCall(PetscViewerRead(viewer, ibuf, icnt, NULL, PETSC_ENUM)); 8129566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, (1 + numNodes) * numElements)); 813de78e4feSLisandro Dalcin for (elem = 0; elem < numElements; ++elem, ++c) { 814de78e4feSLisandro Dalcin GmshElement *element = elements + c; 8150598e1a2SLisandro Dalcin const int *id = ibuf + elem * (1 + numNodes), *nodes = id + 1; 8160598e1a2SLisandro Dalcin element->id = id[0]; 817de78e4feSLisandro Dalcin element->dim = dim; 818de78e4feSLisandro Dalcin element->cellType = cellType; 8190598e1a2SLisandro Dalcin element->numVerts = numVerts; 820de78e4feSLisandro Dalcin element->numNodes = numNodes; 821de78e4feSLisandro Dalcin element->numTags = numTags; 8229566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes)); 8230598e1a2SLisandro Dalcin for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]]; 8240598e1a2SLisandro Dalcin for (p = 0; p < element->numTags; p++) element->tags[p] = entity->tags[p]; 825de78e4feSLisandro Dalcin } 826de78e4feSLisandro Dalcin } 8273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 828698a79b9SLisandro Dalcin } 829698a79b9SLisandro Dalcin 830d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPeriodic_v40(GmshFile *gmsh, PetscInt periodicMap[]) 831d71ae5a4SJacob Faibussowitsch { 832698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 833698a79b9SLisandro Dalcin int fileFormat = gmsh->fileFormat; 834698a79b9SLisandro Dalcin PetscBool binary = gmsh->binary; 835698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 836698a79b9SLisandro Dalcin int numPeriodic, snum, i; 837698a79b9SLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 8380598e1a2SLisandro Dalcin PetscInt *nodeMap = gmsh->nodeMap; 839698a79b9SLisandro Dalcin 840698a79b9SLisandro Dalcin PetscFunctionBegin; 841698a79b9SLisandro Dalcin if (fileFormat == 22 || !binary) { 8429566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 843698a79b9SLisandro Dalcin snum = sscanf(line, "%d", &numPeriodic); 84408401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 845698a79b9SLisandro Dalcin } else { 8469566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numPeriodic, 1, NULL, PETSC_ENUM)); 8479566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numPeriodic, PETSC_ENUM, 1)); 848698a79b9SLisandro Dalcin } 849698a79b9SLisandro Dalcin for (i = 0; i < numPeriodic; i++) { 8509dddd249SSatish Balay int ibuf[3], correspondingDim = -1, correspondingTag = -1, primaryTag = -1, correspondingNode, primaryNode; 851698a79b9SLisandro Dalcin long j, nNodes; 852698a79b9SLisandro Dalcin double affine[16]; 853698a79b9SLisandro Dalcin 854698a79b9SLisandro Dalcin if (fileFormat == 22 || !binary) { 8559566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 3, NULL, PETSC_STRING)); 8569dddd249SSatish Balay snum = sscanf(line, "%d %d %d", &correspondingDim, &correspondingTag, &primaryTag); 85708401ef6SPierre Jolivet PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 858698a79b9SLisandro Dalcin } else { 8599566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM)); 8609566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, 3)); 8619371c9d4SSatish Balay correspondingDim = ibuf[0]; 8629371c9d4SSatish Balay correspondingTag = ibuf[1]; 8639371c9d4SSatish Balay primaryTag = ibuf[2]; 864698a79b9SLisandro Dalcin } 8659371c9d4SSatish Balay (void)correspondingDim; 8669371c9d4SSatish Balay (void)correspondingTag; 8679371c9d4SSatish Balay (void)primaryTag; /* unused */ 868698a79b9SLisandro Dalcin 869698a79b9SLisandro Dalcin if (fileFormat == 22 || !binary) { 8709566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 871698a79b9SLisandro Dalcin snum = sscanf(line, "%ld", &nNodes); 8724c500f23SPierre Jolivet if (snum != 1) { /* discard transformation and try again */ 8739566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, -PETSC_MAX_PATH_LEN, NULL, PETSC_STRING)); 8749566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 875698a79b9SLisandro Dalcin snum = sscanf(line, "%ld", &nNodes); 87608401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 877698a79b9SLisandro Dalcin } 878698a79b9SLisandro Dalcin } else { 8799566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &nNodes, 1, NULL, PETSC_LONG)); 8809566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nNodes, PETSC_LONG, 1)); 8814c500f23SPierre Jolivet if (nNodes == -1) { /* discard transformation and try again */ 8829566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, affine, 16, NULL, PETSC_DOUBLE)); 8839566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &nNodes, 1, NULL, PETSC_LONG)); 8849566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nNodes, PETSC_LONG, 1)); 885698a79b9SLisandro Dalcin } 886698a79b9SLisandro Dalcin } 887698a79b9SLisandro Dalcin 888698a79b9SLisandro Dalcin for (j = 0; j < nNodes; j++) { 889698a79b9SLisandro Dalcin if (fileFormat == 22 || !binary) { 8909566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 2, NULL, PETSC_STRING)); 8919dddd249SSatish Balay snum = sscanf(line, "%d %d", &correspondingNode, &primaryNode); 89208401ef6SPierre Jolivet PetscCheck(snum == 2, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 893698a79b9SLisandro Dalcin } else { 8949566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, 2, NULL, PETSC_ENUM)); 8959566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, 2)); 8969371c9d4SSatish Balay correspondingNode = ibuf[0]; 8979371c9d4SSatish Balay primaryNode = ibuf[1]; 898698a79b9SLisandro Dalcin } 8999dddd249SSatish Balay correspondingNode = (int)nodeMap[correspondingNode]; 9009dddd249SSatish Balay primaryNode = (int)nodeMap[primaryNode]; 9019dddd249SSatish Balay periodicMap[correspondingNode] = primaryNode; 902698a79b9SLisandro Dalcin } 903698a79b9SLisandro Dalcin } 9043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 905698a79b9SLisandro Dalcin } 906698a79b9SLisandro Dalcin 9070598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 908698a79b9SLisandro Dalcin $Entities 909698a79b9SLisandro Dalcin numPoints(size_t) numCurves(size_t) 910698a79b9SLisandro Dalcin numSurfaces(size_t) numVolumes(size_t) 911698a79b9SLisandro Dalcin pointTag(int) X(double) Y(double) Z(double) 912698a79b9SLisandro Dalcin numPhysicalTags(size_t) physicalTag(int) ... 913698a79b9SLisandro Dalcin ... 914698a79b9SLisandro Dalcin curveTag(int) minX(double) minY(double) minZ(double) 915698a79b9SLisandro Dalcin maxX(double) maxY(double) maxZ(double) 916698a79b9SLisandro Dalcin numPhysicalTags(size_t) physicalTag(int) ... 917698a79b9SLisandro Dalcin numBoundingPoints(size_t) pointTag(int) ... 918698a79b9SLisandro Dalcin ... 919698a79b9SLisandro Dalcin surfaceTag(int) minX(double) minY(double) minZ(double) 920698a79b9SLisandro Dalcin maxX(double) maxY(double) maxZ(double) 921698a79b9SLisandro Dalcin numPhysicalTags(size_t) physicalTag(int) ... 922698a79b9SLisandro Dalcin numBoundingCurves(size_t) curveTag(int) ... 923698a79b9SLisandro Dalcin ... 924698a79b9SLisandro Dalcin volumeTag(int) minX(double) minY(double) minZ(double) 925698a79b9SLisandro Dalcin maxX(double) maxY(double) maxZ(double) 926698a79b9SLisandro Dalcin numPhysicalTags(size_t) physicalTag(int) ... 927698a79b9SLisandro Dalcin numBoundngSurfaces(size_t) surfaceTag(int) ... 928698a79b9SLisandro Dalcin ... 929698a79b9SLisandro Dalcin $EndEntities 930698a79b9SLisandro Dalcin */ 931d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEntities_v41(GmshFile *gmsh, GmshMesh *mesh) 932d71ae5a4SJacob Faibussowitsch { 9336497c311SBarry Smith PetscCount count[4], index, numTags; 934698a79b9SLisandro Dalcin int dim, eid, *tags = NULL; 935698a79b9SLisandro Dalcin GmshEntity *entity = NULL; 936698a79b9SLisandro Dalcin 937698a79b9SLisandro Dalcin PetscFunctionBegin; 9386497c311SBarry Smith PetscCall(GmshReadPetscCount(gmsh, count, 4)); 9399566063dSJacob Faibussowitsch PetscCall(GmshEntitiesCreate(count, &mesh->entities)); 940698a79b9SLisandro Dalcin for (dim = 0; dim < 4; ++dim) { 941698a79b9SLisandro Dalcin for (index = 0; index < count[dim]; ++index) { 9429566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, &eid, 1)); 9439566063dSJacob Faibussowitsch PetscCall(GmshEntitiesAdd(mesh->entities, (PetscInt)index, dim, eid, &entity)); 9449566063dSJacob Faibussowitsch PetscCall(GmshReadDouble(gmsh, entity->bbox, (dim == 0) ? 3 : 6)); 9456497c311SBarry Smith PetscCall(GmshReadPetscCount(gmsh, &numTags, 1)); 9469566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, numTags, sizeof(int), &tags)); 9479566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, tags, numTags)); 9486497c311SBarry Smith PetscCheck(numTags <= GMSH_MAX_TAGS, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PETSc currently supports up to %" PetscInt_FMT " tags per entity, not %" PetscCount_FMT, (PetscInt)GMSH_MAX_TAGS, numTags); 9496497c311SBarry Smith PetscCall(PetscIntCast(numTags, &entity->numTags)); 9506497c311SBarry Smith for (PetscInt i = 0; i < entity->numTags; ++i) entity->tags[i] = tags[i]; 951698a79b9SLisandro Dalcin if (dim == 0) continue; 9526497c311SBarry Smith PetscCall(GmshReadPetscCount(gmsh, &numTags, 1)); 9539566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, numTags, sizeof(int), &tags)); 9549566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, tags, numTags)); 95581a1af93SMatthew G. Knepley /* Currently, we do not save the ids for the bounding entities */ 956698a79b9SLisandro Dalcin } 957698a79b9SLisandro Dalcin } 9583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 959698a79b9SLisandro Dalcin } 960698a79b9SLisandro Dalcin 96133a088b6SMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 962698a79b9SLisandro Dalcin $Nodes 963698a79b9SLisandro Dalcin numEntityBlocks(size_t) numNodes(size_t) 964698a79b9SLisandro Dalcin minNodeTag(size_t) maxNodeTag(size_t) 965698a79b9SLisandro Dalcin entityDim(int) entityTag(int) parametric(int; 0 or 1) numNodesBlock(size_t) 966698a79b9SLisandro Dalcin nodeTag(size_t) 967698a79b9SLisandro Dalcin ... 968698a79b9SLisandro Dalcin x(double) y(double) z(double) 969698a79b9SLisandro Dalcin < u(double; if parametric and entityDim = 1 or entityDim = 2) > 970698a79b9SLisandro Dalcin < v(double; if parametric and entityDim = 2) > 971698a79b9SLisandro Dalcin ... 972698a79b9SLisandro Dalcin ... 973698a79b9SLisandro Dalcin $EndNodes 974698a79b9SLisandro Dalcin */ 975d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes_v41(GmshFile *gmsh, GmshMesh *mesh) 976d71ae5a4SJacob Faibussowitsch { 97781a1af93SMatthew G. Knepley int info[3], dim, eid, parametric; 9786497c311SBarry Smith PetscCount sizes[4], numEntityBlocks, numNodes, numNodesBlock = 0; 9796497c311SBarry Smith PetscInt numTags; 98081a1af93SMatthew G. Knepley GmshEntity *entity = NULL; 9810598e1a2SLisandro Dalcin GmshNodes *nodes; 982698a79b9SLisandro Dalcin 983698a79b9SLisandro Dalcin PetscFunctionBegin; 9846497c311SBarry Smith PetscCall(GmshReadPetscCount(gmsh, sizes, 4)); 9859371c9d4SSatish Balay numEntityBlocks = sizes[0]; 9869371c9d4SSatish Balay numNodes = sizes[1]; 9879566063dSJacob Faibussowitsch PetscCall(GmshNodesCreate(numNodes, &nodes)); 9886497c311SBarry Smith PetscCall(PetscIntCast(numNodes, &mesh->numNodes)); 9890598e1a2SLisandro Dalcin mesh->nodelist = nodes; 9906497c311SBarry Smith if (numEntityBlocks && !mesh->entities) PetscCall(PetscInfo(NULL, "File specifies %" PetscCount_FMT " entity blocks, but was missing the $Entities section\n", numEntityBlocks)); 9916497c311SBarry Smith for (PetscCount block = 0, node = 0; block < numEntityBlocks; ++block, node += numNodesBlock) { 9929566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, info, 3)); 9939371c9d4SSatish Balay dim = info[0]; 9949371c9d4SSatish Balay eid = info[1]; 9959371c9d4SSatish Balay parametric = info[2]; 996e43c9757SMatthew G. Knepley if (mesh->entities) PetscCall(GmshEntitiesGet(mesh->entities, dim, eid, &entity)); 997e43c9757SMatthew G. Knepley numTags = entity ? entity->numTags : 0; 99881a1af93SMatthew G. Knepley PetscCheck(!parametric, PETSC_COMM_SELF, PETSC_ERR_SUP, "Parametric coordinates not supported"); 9996497c311SBarry Smith PetscCall(GmshReadPetscCount(gmsh, &numNodesBlock, 1)); 10006497c311SBarry Smith PetscCall(GmshReadPetscInt(gmsh, nodes->id + node, numNodesBlock)); 10019566063dSJacob Faibussowitsch PetscCall(GmshReadDouble(gmsh, nodes->xyz + node * 3, numNodesBlock * 3)); 10026497c311SBarry Smith for (PetscCount n = 0; n < numNodesBlock; ++n) { 10037d5b9244SMatthew G. Knepley PetscInt *tags = &nodes->tag[node * GMSH_MAX_TAGS]; 10047d5b9244SMatthew G. Knepley 10056497c311SBarry Smith for (PetscInt t = 0; t < numTags; ++t) tags[n * GMSH_MAX_TAGS + t] = entity->tags[t]; 10066497c311SBarry Smith for (PetscInt t = numTags; t < GMSH_MAX_TAGS; ++t) tags[n * GMSH_MAX_TAGS + t] = -1; 10077d5b9244SMatthew G. Knepley } 1008698a79b9SLisandro Dalcin } 10096497c311SBarry Smith PetscCall(PetscIntCast(sizes[2], &gmsh->nodeStart)); 10106497c311SBarry Smith PetscCall(PetscIntCast(sizes[3] + 1, &gmsh->nodeEnd)); 10113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1012698a79b9SLisandro Dalcin } 1013698a79b9SLisandro Dalcin 101433a088b6SMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 1015698a79b9SLisandro Dalcin $Elements 1016698a79b9SLisandro Dalcin numEntityBlocks(size_t) numElements(size_t) 1017698a79b9SLisandro Dalcin minElementTag(size_t) maxElementTag(size_t) 1018698a79b9SLisandro Dalcin entityDim(int) entityTag(int) elementType(int; see below) numElementsBlock(size_t) 1019698a79b9SLisandro Dalcin elementTag(size_t) nodeTag(size_t) ... 1020698a79b9SLisandro Dalcin ... 1021698a79b9SLisandro Dalcin ... 1022698a79b9SLisandro Dalcin $EndElements 1023698a79b9SLisandro Dalcin */ 1024d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements_v41(GmshFile *gmsh, GmshMesh *mesh) 1025d71ae5a4SJacob Faibussowitsch { 10260598e1a2SLisandro Dalcin int info[3], eid, dim, cellType; 10276497c311SBarry Smith PetscCount sizes[4], numEntityBlocks, numElements, numBlockElements, numVerts, numNodes, numTags, block, elem, c, p; 1028698a79b9SLisandro Dalcin GmshEntity *entity = NULL; 1029698a79b9SLisandro Dalcin GmshElement *elements; 10306497c311SBarry Smith PetscInt *nodeMap = gmsh->nodeMap, *ibuf = NULL; 1031698a79b9SLisandro Dalcin 1032698a79b9SLisandro Dalcin PetscFunctionBegin; 10336497c311SBarry Smith PetscCall(GmshReadPetscCount(gmsh, sizes, 4)); 10349371c9d4SSatish Balay numEntityBlocks = sizes[0]; 10359371c9d4SSatish Balay numElements = sizes[1]; 10369566063dSJacob Faibussowitsch PetscCall(GmshElementsCreate(numElements, &elements)); 10376497c311SBarry Smith PetscCall(PetscIntCast(numElements, &mesh->numElems)); 10380598e1a2SLisandro Dalcin mesh->elements = elements; 10396497c311SBarry Smith if (numEntityBlocks && !mesh->entities) PetscCall(PetscInfo(NULL, "File specifies %" PetscCount_FMT " entity blocks, but was missing the $Entities section\n", numEntityBlocks)); 1040698a79b9SLisandro Dalcin for (c = 0, block = 0; block < numEntityBlocks; ++block) { 10419566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, info, 3)); 10429371c9d4SSatish Balay dim = info[0]; 10439371c9d4SSatish Balay eid = info[1]; 10449371c9d4SSatish Balay cellType = info[2]; 1045e43c9757SMatthew G. Knepley if (mesh->entities) PetscCall(GmshEntitiesGet(mesh->entities, dim, eid, &entity)); 10469566063dSJacob Faibussowitsch PetscCall(GmshCellTypeCheck(cellType)); 10470598e1a2SLisandro Dalcin numVerts = GmshCellMap[cellType].numVerts; 10480598e1a2SLisandro Dalcin numNodes = GmshCellMap[cellType].numNodes; 1049e43c9757SMatthew G. Knepley numTags = entity ? entity->numTags : 0; 10506497c311SBarry Smith PetscCall(GmshReadPetscCount(gmsh, &numBlockElements, 1)); 10519566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, (1 + numNodes) * numBlockElements, sizeof(PetscInt), &ibuf)); 10526497c311SBarry Smith PetscCall(GmshReadPetscInt(gmsh, ibuf, (1 + numNodes) * numBlockElements)); 1053698a79b9SLisandro Dalcin for (elem = 0; elem < numBlockElements; ++elem, ++c) { 1054698a79b9SLisandro Dalcin GmshElement *element = elements + c; 10550598e1a2SLisandro Dalcin const PetscInt *id = ibuf + elem * (1 + numNodes), *nodes = id + 1; 10566497c311SBarry Smith 1057698a79b9SLisandro Dalcin element->id = id[0]; 1058698a79b9SLisandro Dalcin element->dim = dim; 1059698a79b9SLisandro Dalcin element->cellType = cellType; 10606497c311SBarry Smith PetscCall(PetscIntCast(numVerts, &element->numVerts)); 10616497c311SBarry Smith PetscCall(PetscIntCast(numNodes, &element->numNodes)); 10626497c311SBarry Smith PetscCall(PetscIntCast(numTags, &element->numTags)); 10636497c311SBarry Smith PetscCall(PetscSegBufferGet(mesh->segbuf, element->numNodes, &element->nodes)); 10640598e1a2SLisandro Dalcin for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]]; 10650598e1a2SLisandro Dalcin for (p = 0; p < element->numTags; p++) element->tags[p] = entity->tags[p]; 1066698a79b9SLisandro Dalcin } 1067698a79b9SLisandro Dalcin } 10683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1069698a79b9SLisandro Dalcin } 1070698a79b9SLisandro Dalcin 10710598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 1072698a79b9SLisandro Dalcin $Periodic 1073698a79b9SLisandro Dalcin numPeriodicLinks(size_t) 10749dddd249SSatish Balay entityDim(int) entityTag(int) entityTagPrimary(int) 1075698a79b9SLisandro Dalcin numAffine(size_t) value(double) ... 1076698a79b9SLisandro Dalcin numCorrespondingNodes(size_t) 10779dddd249SSatish Balay nodeTag(size_t) nodeTagPrimary(size_t) 1078698a79b9SLisandro Dalcin ... 1079698a79b9SLisandro Dalcin ... 1080698a79b9SLisandro Dalcin $EndPeriodic 1081698a79b9SLisandro Dalcin */ 1082d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPeriodic_v41(GmshFile *gmsh, PetscInt periodicMap[]) 1083d71ae5a4SJacob Faibussowitsch { 1084698a79b9SLisandro Dalcin int info[3]; 1085698a79b9SLisandro Dalcin double dbuf[16]; 10866497c311SBarry Smith PetscCount numPeriodicLinks, numAffine, numCorrespondingNodes; 10876497c311SBarry Smith PetscInt *nodeMap = gmsh->nodeMap, *nodeTags = NULL; 1088698a79b9SLisandro Dalcin 1089698a79b9SLisandro Dalcin PetscFunctionBegin; 10906497c311SBarry Smith PetscCall(GmshReadPetscCount(gmsh, &numPeriodicLinks, 1)); 10916497c311SBarry Smith for (PetscCount link = 0; link < numPeriodicLinks; ++link) { 10929566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, info, 3)); 10936497c311SBarry Smith PetscCall(GmshReadPetscCount(gmsh, &numAffine, 1)); 10949566063dSJacob Faibussowitsch PetscCall(GmshReadDouble(gmsh, dbuf, numAffine)); 10956497c311SBarry Smith PetscCall(GmshReadPetscCount(gmsh, &numCorrespondingNodes, 1)); 10969566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, numCorrespondingNodes, sizeof(PetscInt), &nodeTags)); 10976497c311SBarry Smith PetscCall(GmshReadPetscInt(gmsh, nodeTags, numCorrespondingNodes * 2)); 10986497c311SBarry Smith for (PetscCount node = 0; node < numCorrespondingNodes; ++node) { 10999dddd249SSatish Balay PetscInt correspondingNode = nodeMap[nodeTags[node * 2 + 0]]; 11009dddd249SSatish Balay PetscInt primaryNode = nodeMap[nodeTags[node * 2 + 1]]; 11016497c311SBarry Smith 11029dddd249SSatish Balay periodicMap[correspondingNode] = primaryNode; 1103698a79b9SLisandro Dalcin } 1104698a79b9SLisandro Dalcin } 11053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1106698a79b9SLisandro Dalcin } 1107698a79b9SLisandro Dalcin 11080598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 1109d6689ca9SLisandro Dalcin $MeshFormat // same as MSH version 2 1110d6689ca9SLisandro Dalcin version(ASCII double; currently 4.1) 1111d6689ca9SLisandro Dalcin file-type(ASCII int; 0 for ASCII mode, 1 for binary mode) 1112d6689ca9SLisandro Dalcin data-size(ASCII int; sizeof(size_t)) 1113d6689ca9SLisandro Dalcin < int with value one; only in binary mode, to detect endianness > 1114d6689ca9SLisandro Dalcin $EndMeshFormat 1115d6689ca9SLisandro Dalcin */ 1116d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadMeshFormat(GmshFile *gmsh) 1117d71ae5a4SJacob Faibussowitsch { 1118698a79b9SLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 1119698a79b9SLisandro Dalcin int snum, fileType, fileFormat, dataSize, checkEndian; 1120698a79b9SLisandro Dalcin float version; 1121698a79b9SLisandro Dalcin 1122698a79b9SLisandro Dalcin PetscFunctionBegin; 11239566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 3)); 1124698a79b9SLisandro Dalcin snum = sscanf(line, "%f %d %d", &version, &fileType, &dataSize); 1125a8d4e440SJunchao Zhang fileFormat = (int)roundf(version * 10); 112608401ef6SPierre Jolivet PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line); 1127a8d4e440SJunchao Zhang PetscCheck(fileFormat >= 22, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at least 2.2", (double)version); 11281dca8a05SBarry Smith PetscCheck((int)version != 3, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f not supported", (double)version); 1129a8d4e440SJunchao Zhang PetscCheck(fileFormat <= 41, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at most 4.1", (double)version); 113008401ef6SPierre Jolivet PetscCheck(!gmsh->binary || fileType, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Viewer is binary but Gmsh file is ASCII"); 113108401ef6SPierre Jolivet PetscCheck(gmsh->binary || !fileType, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Viewer is ASCII but Gmsh file is binary"); 11321dca8a05SBarry 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); 11331dca8a05SBarry 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); 1134698a79b9SLisandro Dalcin gmsh->fileFormat = fileFormat; 1135698a79b9SLisandro Dalcin gmsh->dataSize = dataSize; 1136698a79b9SLisandro Dalcin gmsh->byteSwap = PETSC_FALSE; 1137698a79b9SLisandro Dalcin if (gmsh->binary) { 11389566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, &checkEndian, 1)); 1139698a79b9SLisandro Dalcin if (checkEndian != 1) { 11409566063dSJacob Faibussowitsch PetscCall(PetscByteSwap(&checkEndian, PETSC_ENUM, 1)); 114108401ef6SPierre Jolivet PetscCheck(checkEndian == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to detect endianness in Gmsh file header: %s", line); 1142698a79b9SLisandro Dalcin gmsh->byteSwap = PETSC_TRUE; 1143698a79b9SLisandro Dalcin } 1144698a79b9SLisandro Dalcin } 11453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1146698a79b9SLisandro Dalcin } 1147698a79b9SLisandro Dalcin 11488749820aSMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 11498749820aSMatthew G. Knepley Neper: https://neper.info/ adds this section 11508749820aSMatthew G. Knepley 11518749820aSMatthew G. Knepley $MeshVersion 11528749820aSMatthew G. Knepley <major>.<minor>,<patch> 11538749820aSMatthew G. Knepley $EndMeshVersion 11548749820aSMatthew G. Knepley */ 11558749820aSMatthew G. Knepley static PetscErrorCode GmshReadMeshVersion(GmshFile *gmsh) 11568749820aSMatthew G. Knepley { 11578749820aSMatthew G. Knepley char line[PETSC_MAX_PATH_LEN]; 11588749820aSMatthew G. Knepley int snum, major, minor, patch; 11598749820aSMatthew G. Knepley 11608749820aSMatthew G. Knepley PetscFunctionBegin; 11618749820aSMatthew G. Knepley PetscCall(GmshReadString(gmsh, line, 1)); 11628749820aSMatthew G. Knepley snum = sscanf(line, "%d.%d.%d", &major, &minor, &patch); 11638749820aSMatthew G. Knepley PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line); 11648749820aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 11658749820aSMatthew G. Knepley } 11668749820aSMatthew G. Knepley 11678749820aSMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 11688749820aSMatthew G. Knepley Neper: https://neper.info/ adds this section 11698749820aSMatthew G. Knepley 11708749820aSMatthew G. Knepley $Domain 11718749820aSMatthew G. Knepley <shape> 11728749820aSMatthew G. Knepley $EndDomain 11738749820aSMatthew G. Knepley */ 11748749820aSMatthew G. Knepley static PetscErrorCode GmshReadMeshDomain(GmshFile *gmsh) 11758749820aSMatthew G. Knepley { 11768749820aSMatthew G. Knepley char line[PETSC_MAX_PATH_LEN]; 11778749820aSMatthew G. Knepley 11788749820aSMatthew G. Knepley PetscFunctionBegin; 11798749820aSMatthew G. Knepley PetscCall(GmshReadString(gmsh, line, 1)); 11808749820aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 11818749820aSMatthew G. Knepley } 11828749820aSMatthew G. Knepley 11831f643af3SLisandro Dalcin /* 11841f643af3SLisandro Dalcin PhysicalNames 11851f643af3SLisandro Dalcin numPhysicalNames(ASCII int) 11861f643af3SLisandro Dalcin dimension(ASCII int) physicalTag(ASCII int) "name"(127 characters max) 11871f643af3SLisandro Dalcin ... 11881f643af3SLisandro Dalcin $EndPhysicalNames 11891f643af3SLisandro Dalcin */ 1190d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPhysicalNames(GmshFile *gmsh, GmshMesh *mesh) 1191d71ae5a4SJacob Faibussowitsch { 1192bbcf679cSJacob Faibussowitsch char line[PETSC_MAX_PATH_LEN], name[128 + 2], *p = NULL, *q = NULL, *r = NULL; 1193a45dabc8SMatthew G. Knepley int snum, region, dim, tag; 1194698a79b9SLisandro Dalcin 1195698a79b9SLisandro Dalcin PetscFunctionBegin; 11969566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 1)); 1197a45dabc8SMatthew G. Knepley snum = sscanf(line, "%d", ®ion); 1198a45dabc8SMatthew G. Knepley mesh->numRegions = region; 119908401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 120090d778b8SLisandro Dalcin PetscCall(PetscMalloc3(mesh->numRegions, &mesh->regionDims, mesh->numRegions, &mesh->regionTags, mesh->numRegions, &mesh->regionNames)); 1201a45dabc8SMatthew G. Knepley for (region = 0; region < mesh->numRegions; ++region) { 12029566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 2)); 12031f643af3SLisandro Dalcin snum = sscanf(line, "%d %d", &dim, &tag); 120408401ef6SPierre Jolivet PetscCheck(snum == 2, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 12059566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, -(PetscInt)sizeof(line))); 12069566063dSJacob Faibussowitsch PetscCall(PetscStrchr(line, '"', &p)); 120728b400f6SJacob Faibussowitsch PetscCheck(p, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 12089566063dSJacob Faibussowitsch PetscCall(PetscStrrchr(line, '"', &q)); 120908401ef6SPierre Jolivet PetscCheck(q != p, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 12105f5cd6d5SMatthew G. Knepley PetscCall(PetscStrrchr(line, ':', &r)); 12115f5cd6d5SMatthew G. Knepley if (p != r) q = r; 12129566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(name, p + 1, (size_t)(q - p - 1))); 121390d778b8SLisandro Dalcin mesh->regionDims[region] = dim; 1214a45dabc8SMatthew G. Knepley mesh->regionTags[region] = tag; 12159566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(name, &mesh->regionNames[region])); 1216698a79b9SLisandro Dalcin } 12173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1218de78e4feSLisandro Dalcin } 1219de78e4feSLisandro Dalcin 1220d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEntities(GmshFile *gmsh, GmshMesh *mesh) 1221d71ae5a4SJacob Faibussowitsch { 12220598e1a2SLisandro Dalcin PetscFunctionBegin; 12230598e1a2SLisandro Dalcin switch (gmsh->fileFormat) { 1224d71ae5a4SJacob Faibussowitsch case 41: 1225d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadEntities_v41(gmsh, mesh)); 1226d71ae5a4SJacob Faibussowitsch break; 1227d71ae5a4SJacob Faibussowitsch default: 1228d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadEntities_v40(gmsh, mesh)); 1229d71ae5a4SJacob Faibussowitsch break; 123096ca5757SLisandro Dalcin } 12313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12320598e1a2SLisandro Dalcin } 12330598e1a2SLisandro Dalcin 1234d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes(GmshFile *gmsh, GmshMesh *mesh) 1235d71ae5a4SJacob Faibussowitsch { 12360598e1a2SLisandro Dalcin PetscFunctionBegin; 12370598e1a2SLisandro Dalcin switch (gmsh->fileFormat) { 1238d71ae5a4SJacob Faibussowitsch case 41: 1239d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadNodes_v41(gmsh, mesh)); 1240d71ae5a4SJacob Faibussowitsch break; 1241d71ae5a4SJacob Faibussowitsch case 40: 1242d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadNodes_v40(gmsh, mesh)); 1243d71ae5a4SJacob Faibussowitsch break; 1244d71ae5a4SJacob Faibussowitsch default: 1245d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadNodes_v22(gmsh, mesh)); 1246d71ae5a4SJacob Faibussowitsch break; 12470598e1a2SLisandro Dalcin } 12480598e1a2SLisandro Dalcin 12490598e1a2SLisandro Dalcin { /* Gmsh v2.2/v4.0 does not provide min/max node tags */ 12500598e1a2SLisandro Dalcin if (mesh->numNodes > 0 && gmsh->nodeEnd >= gmsh->nodeStart) { 12511690c2aeSBarry Smith PetscInt tagMin = PETSC_INT_MAX, tagMax = PETSC_INT_MIN, n; 12520598e1a2SLisandro Dalcin GmshNodes *nodes = mesh->nodelist; 12530598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) { 12540598e1a2SLisandro Dalcin const PetscInt tag = nodes->id[n]; 12550598e1a2SLisandro Dalcin tagMin = PetscMin(tag, tagMin); 12560598e1a2SLisandro Dalcin tagMax = PetscMax(tag, tagMax); 12570598e1a2SLisandro Dalcin } 12580598e1a2SLisandro Dalcin gmsh->nodeStart = tagMin; 12590598e1a2SLisandro Dalcin gmsh->nodeEnd = tagMax + 1; 12600598e1a2SLisandro Dalcin } 12610598e1a2SLisandro Dalcin } 12620598e1a2SLisandro Dalcin 12630598e1a2SLisandro Dalcin { /* Support for sparse node tags */ 12640598e1a2SLisandro Dalcin PetscInt n, t; 12650598e1a2SLisandro Dalcin GmshNodes *nodes = mesh->nodelist; 12669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(gmsh->nodeEnd - gmsh->nodeStart, &gmsh->nbuf)); 12671690c2aeSBarry Smith for (t = 0; t < gmsh->nodeEnd - gmsh->nodeStart; ++t) gmsh->nbuf[t] = PETSC_INT_MIN; 12680598e1a2SLisandro Dalcin gmsh->nodeMap = gmsh->nbuf - gmsh->nodeStart; 12690598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) { 12700598e1a2SLisandro Dalcin const PetscInt tag = nodes->id[n]; 127163a3b9bcSJacob Faibussowitsch PetscCheck(gmsh->nodeMap[tag] < 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Repeated node tag %" PetscInt_FMT, tag); 12720598e1a2SLisandro Dalcin gmsh->nodeMap[tag] = n; 12730598e1a2SLisandro Dalcin } 12740598e1a2SLisandro Dalcin } 12753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12760598e1a2SLisandro Dalcin } 12770598e1a2SLisandro Dalcin 1278d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements(GmshFile *gmsh, GmshMesh *mesh) 1279d71ae5a4SJacob Faibussowitsch { 12800598e1a2SLisandro Dalcin PetscFunctionBegin; 12810598e1a2SLisandro Dalcin switch (gmsh->fileFormat) { 1282d71ae5a4SJacob Faibussowitsch case 41: 1283d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadElements_v41(gmsh, mesh)); 1284d71ae5a4SJacob Faibussowitsch break; 1285d71ae5a4SJacob Faibussowitsch case 40: 1286d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadElements_v40(gmsh, mesh)); 1287d71ae5a4SJacob Faibussowitsch break; 1288d71ae5a4SJacob Faibussowitsch default: 1289d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadElements_v22(gmsh, mesh)); 1290d71ae5a4SJacob Faibussowitsch break; 12910598e1a2SLisandro Dalcin } 12920598e1a2SLisandro Dalcin 12930598e1a2SLisandro Dalcin { /* Reorder elements by codimension and polytope type */ 12940598e1a2SLisandro Dalcin PetscInt ne = mesh->numElems; 12950598e1a2SLisandro Dalcin GmshElement *elements = mesh->elements; 1296066ea43fSLisandro Dalcin PetscInt keymap[GMSH_NUM_POLYTOPES], nk = 0; 1297066ea43fSLisandro Dalcin PetscInt offset[GMSH_NUM_POLYTOPES + 1], e, k; 12980598e1a2SLisandro Dalcin 12991690c2aeSBarry Smith for (k = 0; k < GMSH_NUM_POLYTOPES; ++k) keymap[k] = PETSC_INT_MIN; 13009566063dSJacob Faibussowitsch PetscCall(PetscMemzero(offset, sizeof(offset))); 13010598e1a2SLisandro Dalcin 1302066ea43fSLisandro Dalcin keymap[GMSH_TET] = nk++; 1303066ea43fSLisandro Dalcin keymap[GMSH_HEX] = nk++; 1304066ea43fSLisandro Dalcin keymap[GMSH_PRI] = nk++; 1305066ea43fSLisandro Dalcin keymap[GMSH_PYR] = nk++; 1306066ea43fSLisandro Dalcin keymap[GMSH_TRI] = nk++; 1307066ea43fSLisandro Dalcin keymap[GMSH_QUA] = nk++; 1308066ea43fSLisandro Dalcin keymap[GMSH_SEG] = nk++; 1309066ea43fSLisandro Dalcin keymap[GMSH_VTX] = nk++; 13100598e1a2SLisandro Dalcin 13119566063dSJacob Faibussowitsch PetscCall(GmshElementsCreate(mesh->numElems, &mesh->elements)); 13124ad8454bSPierre Jolivet #define key(eid) keymap[GmshCellMap[elements[eid].cellType].polytope] 13130598e1a2SLisandro Dalcin for (e = 0; e < ne; ++e) offset[1 + key(e)]++; 13140598e1a2SLisandro Dalcin for (k = 1; k < nk; ++k) offset[k] += offset[k - 1]; 13150598e1a2SLisandro Dalcin for (e = 0; e < ne; ++e) mesh->elements[offset[key(e)]++] = elements[e]; 13160598e1a2SLisandro Dalcin #undef key 13179566063dSJacob Faibussowitsch PetscCall(GmshElementsDestroy(&elements)); 1318066ea43fSLisandro Dalcin } 13190598e1a2SLisandro Dalcin 1320066ea43fSLisandro Dalcin { /* Mesh dimension and order */ 1321066ea43fSLisandro Dalcin GmshElement *elem = mesh->numElems ? mesh->elements : NULL; 1322066ea43fSLisandro Dalcin mesh->dim = elem ? GmshCellMap[elem->cellType].dim : 0; 1323066ea43fSLisandro Dalcin mesh->order = elem ? GmshCellMap[elem->cellType].order : 0; 13240598e1a2SLisandro Dalcin } 13250598e1a2SLisandro Dalcin 13260598e1a2SLisandro Dalcin { 13270598e1a2SLisandro Dalcin PetscBT vtx; 13280598e1a2SLisandro Dalcin PetscInt dim = mesh->dim, e, n, v; 13290598e1a2SLisandro Dalcin 13309566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(mesh->numNodes, &vtx)); 13310598e1a2SLisandro Dalcin 13320598e1a2SLisandro Dalcin /* Compute number of cells and set of vertices */ 13330598e1a2SLisandro Dalcin mesh->numCells = 0; 13340598e1a2SLisandro Dalcin for (e = 0; e < mesh->numElems; ++e) { 13350598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + e; 13360598e1a2SLisandro Dalcin if (elem->dim == dim && dim > 0) mesh->numCells++; 133748a46eb9SPierre Jolivet for (v = 0; v < elem->numVerts; v++) PetscCall(PetscBTSet(vtx, elem->nodes[v])); 13380598e1a2SLisandro Dalcin } 13390598e1a2SLisandro Dalcin 13400598e1a2SLisandro Dalcin /* Compute numbering for vertices */ 13410598e1a2SLisandro Dalcin mesh->numVerts = 0; 13429566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mesh->numNodes, &mesh->vertexMap)); 13431690c2aeSBarry Smith for (n = 0; n < mesh->numNodes; ++n) mesh->vertexMap[n] = PetscBTLookup(vtx, n) ? mesh->numVerts++ : PETSC_INT_MIN; 13440598e1a2SLisandro Dalcin 13459566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&vtx)); 13460598e1a2SLisandro Dalcin } 13473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13480598e1a2SLisandro Dalcin } 13490598e1a2SLisandro Dalcin 1350d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPeriodic(GmshFile *gmsh, GmshMesh *mesh) 1351d71ae5a4SJacob Faibussowitsch { 13520598e1a2SLisandro Dalcin PetscInt n; 13530598e1a2SLisandro Dalcin 13540598e1a2SLisandro Dalcin PetscFunctionBegin; 13559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mesh->numNodes, &mesh->periodMap)); 13560598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) mesh->periodMap[n] = n; 13570598e1a2SLisandro Dalcin switch (gmsh->fileFormat) { 1358d71ae5a4SJacob Faibussowitsch case 41: 1359d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadPeriodic_v41(gmsh, mesh->periodMap)); 1360d71ae5a4SJacob Faibussowitsch break; 1361d71ae5a4SJacob Faibussowitsch default: 1362d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadPeriodic_v40(gmsh, mesh->periodMap)); 1363d71ae5a4SJacob Faibussowitsch break; 13640598e1a2SLisandro Dalcin } 13650598e1a2SLisandro Dalcin 13669dddd249SSatish Balay /* Find canonical primary nodes */ 13670598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) 13689371c9d4SSatish Balay while (mesh->periodMap[n] != mesh->periodMap[mesh->periodMap[n]]) mesh->periodMap[n] = mesh->periodMap[mesh->periodMap[n]]; 13690598e1a2SLisandro Dalcin 13709dddd249SSatish Balay /* Renumber vertices (filter out correspondings) */ 13710598e1a2SLisandro Dalcin mesh->numVerts = 0; 13720598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) 13730598e1a2SLisandro Dalcin if (mesh->vertexMap[n] >= 0) /* is vertex */ 13749dddd249SSatish Balay if (mesh->periodMap[n] == n) /* is primary */ 13750598e1a2SLisandro Dalcin mesh->vertexMap[n] = mesh->numVerts++; 13760598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) 13770598e1a2SLisandro Dalcin if (mesh->vertexMap[n] >= 0) /* is vertex */ 13789dddd249SSatish Balay if (mesh->periodMap[n] != n) /* is corresponding */ 13790598e1a2SLisandro Dalcin mesh->vertexMap[n] = mesh->vertexMap[mesh->periodMap[n]]; 13803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13810598e1a2SLisandro Dalcin } 13820598e1a2SLisandro Dalcin 1383066ea43fSLisandro Dalcin #define DM_POLYTOPE_VERTEX DM_POLYTOPE_POINT 1384066ea43fSLisandro Dalcin static const DMPolytopeType DMPolytopeMap[] = { 1385066ea43fSLisandro Dalcin /* GMSH_VTX */ DM_POLYTOPE_VERTEX, 1386066ea43fSLisandro Dalcin /* GMSH_SEG */ DM_POLYTOPE_SEGMENT, 1387066ea43fSLisandro Dalcin /* GMSH_TRI */ DM_POLYTOPE_TRIANGLE, 1388066ea43fSLisandro Dalcin /* GMSH_QUA */ DM_POLYTOPE_QUADRILATERAL, 1389066ea43fSLisandro Dalcin /* GMSH_TET */ DM_POLYTOPE_TETRAHEDRON, 1390066ea43fSLisandro Dalcin /* GMSH_HEX */ DM_POLYTOPE_HEXAHEDRON, 1391066ea43fSLisandro Dalcin /* GMSH_PRI */ DM_POLYTOPE_TRI_PRISM, 13929371c9d4SSatish Balay /* GMSH_PYR */ DM_POLYTOPE_PYRAMID, DM_POLYTOPE_UNKNOWN}; 13930598e1a2SLisandro Dalcin 1394d71ae5a4SJacob Faibussowitsch static inline DMPolytopeType DMPolytopeTypeFromGmsh(PetscInt cellType) 1395d71ae5a4SJacob Faibussowitsch { 1396066ea43fSLisandro Dalcin return DMPolytopeMap[GmshCellMap[cellType].polytope]; 1397066ea43fSLisandro Dalcin } 1398066ea43fSLisandro Dalcin 1399d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshCreateFE(MPI_Comm comm, const char prefix[], PetscBool isSimplex, PetscBool continuity, PetscDTNodeType nodeType, PetscInt dim, PetscInt Nc, PetscInt k, PetscFE *fem) 1400d71ae5a4SJacob Faibussowitsch { 1401066ea43fSLisandro Dalcin DM K; 1402066ea43fSLisandro Dalcin PetscSpace P; 1403066ea43fSLisandro Dalcin PetscDualSpace Q; 1404066ea43fSLisandro Dalcin PetscQuadrature q, fq; 1405066ea43fSLisandro Dalcin PetscBool isTensor = isSimplex ? PETSC_FALSE : PETSC_TRUE; 1406066ea43fSLisandro Dalcin PetscBool endpoint = PETSC_TRUE; 1407066ea43fSLisandro Dalcin char name[32]; 1408066ea43fSLisandro Dalcin 1409066ea43fSLisandro Dalcin PetscFunctionBegin; 1410066ea43fSLisandro Dalcin /* Create space */ 14119566063dSJacob Faibussowitsch PetscCall(PetscSpaceCreate(comm, &P)); 14129566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetType(P, PETSCSPACEPOLYNOMIAL)); 14139566063dSJacob Faibussowitsch PetscCall(PetscSpacePolynomialSetTensor(P, isTensor)); 14149566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumComponents(P, Nc)); 14159566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumVariables(P, dim)); 14169566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetDegree(P, k, PETSC_DETERMINE)); 1417066ea43fSLisandro Dalcin if (prefix) { 14189566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)P, prefix)); 14199566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetFromOptions(P)); 14209566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)P, NULL)); 14219566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetDegree(P, &k, NULL)); 1422066ea43fSLisandro Dalcin } 14239566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetUp(P)); 1424066ea43fSLisandro Dalcin /* Create dual space */ 14259566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceCreate(comm, &Q)); 14269566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetType(Q, PETSCDUALSPACELAGRANGE)); 14279566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceLagrangeSetTensor(Q, isTensor)); 14289566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceLagrangeSetContinuity(Q, continuity)); 14299566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceLagrangeSetNodeType(Q, nodeType, endpoint, 0)); 14309566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetNumComponents(Q, Nc)); 14319566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetOrder(Q, k)); 14329566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell(PETSC_COMM_SELF, DMPolytopeTypeSimpleShape(dim, isSimplex), &K)); 14339566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetDM(Q, K)); 14349566063dSJacob Faibussowitsch PetscCall(DMDestroy(&K)); 1435066ea43fSLisandro Dalcin if (prefix) { 14369566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)Q, prefix)); 14379566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetFromOptions(Q)); 14389566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)Q, NULL)); 1439066ea43fSLisandro Dalcin } 14409566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetUp(Q)); 1441066ea43fSLisandro Dalcin /* Create quadrature */ 1442066ea43fSLisandro Dalcin if (isSimplex) { 14439566063dSJacob Faibussowitsch PetscCall(PetscDTStroudConicalQuadrature(dim, 1, k + 1, -1, +1, &q)); 14449566063dSJacob Faibussowitsch PetscCall(PetscDTStroudConicalQuadrature(dim - 1, 1, k + 1, -1, +1, &fq)); 1445066ea43fSLisandro Dalcin } else { 14469566063dSJacob Faibussowitsch PetscCall(PetscDTGaussTensorQuadrature(dim, 1, k + 1, -1, +1, &q)); 14479566063dSJacob Faibussowitsch PetscCall(PetscDTGaussTensorQuadrature(dim - 1, 1, k + 1, -1, +1, &fq)); 1448066ea43fSLisandro Dalcin } 1449066ea43fSLisandro Dalcin /* Create finite element */ 14509566063dSJacob Faibussowitsch PetscCall(PetscFECreate(comm, fem)); 14519566063dSJacob Faibussowitsch PetscCall(PetscFESetType(*fem, PETSCFEBASIC)); 14529566063dSJacob Faibussowitsch PetscCall(PetscFESetNumComponents(*fem, Nc)); 14539566063dSJacob Faibussowitsch PetscCall(PetscFESetBasisSpace(*fem, P)); 14549566063dSJacob Faibussowitsch PetscCall(PetscFESetDualSpace(*fem, Q)); 14559566063dSJacob Faibussowitsch PetscCall(PetscFESetQuadrature(*fem, q)); 14569566063dSJacob Faibussowitsch PetscCall(PetscFESetFaceQuadrature(*fem, fq)); 1457066ea43fSLisandro Dalcin if (prefix) { 14589566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*fem, prefix)); 14599566063dSJacob Faibussowitsch PetscCall(PetscFESetFromOptions(*fem)); 14609566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*fem, NULL)); 1461066ea43fSLisandro Dalcin } 14629566063dSJacob Faibussowitsch PetscCall(PetscFESetUp(*fem)); 1463066ea43fSLisandro Dalcin /* Cleanup */ 14649566063dSJacob Faibussowitsch PetscCall(PetscSpaceDestroy(&P)); 14659566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceDestroy(&Q)); 14669566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&q)); 14679566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&fq)); 1468066ea43fSLisandro Dalcin /* Set finite element name */ 146963a3b9bcSJacob Faibussowitsch PetscCall(PetscSNPrintf(name, sizeof(name), "%s%" PetscInt_FMT, isSimplex ? "P" : "Q", k)); 14709566063dSJacob Faibussowitsch PetscCall(PetscFESetName(*fem, name)); 14713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 147296ca5757SLisandro Dalcin } 147396ca5757SLisandro Dalcin 1474cc4c1da9SBarry Smith /*@ 1475a1cb98faSBarry Smith DMPlexCreateGmshFromFile - Create a `DMPLEX` mesh from a Gmsh file 1476d6689ca9SLisandro Dalcin 1477a4e35b19SJacob Faibussowitsch Input Parameters: 1478d6689ca9SLisandro Dalcin + comm - The MPI communicator 1479d6689ca9SLisandro Dalcin . filename - Name of the Gmsh file 1480d6689ca9SLisandro Dalcin - interpolate - Create faces and edges in the mesh 1481d6689ca9SLisandro Dalcin 1482d6689ca9SLisandro Dalcin Output Parameter: 1483a1cb98faSBarry Smith . dm - The `DM` object representing the mesh 1484d6689ca9SLisandro Dalcin 1485d6689ca9SLisandro Dalcin Level: beginner 1486d6689ca9SLisandro Dalcin 14871cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()` 1488d6689ca9SLisandro Dalcin @*/ 1489d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateGmshFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) 1490d71ae5a4SJacob Faibussowitsch { 1491d6689ca9SLisandro Dalcin PetscViewer viewer; 1492d6689ca9SLisandro Dalcin PetscMPIInt rank; 1493d6689ca9SLisandro Dalcin int fileType; 1494d6689ca9SLisandro Dalcin PetscViewerType vtype; 1495d6689ca9SLisandro Dalcin 1496d6689ca9SLisandro Dalcin PetscFunctionBegin; 14979566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1498d6689ca9SLisandro Dalcin 1499d6689ca9SLisandro Dalcin /* Determine Gmsh file type (ASCII or binary) from file header */ 1500dd400576SPatrick Sanan if (rank == 0) { 15010598e1a2SLisandro Dalcin GmshFile gmsh[1]; 1502d6689ca9SLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 1503d6689ca9SLisandro Dalcin int snum; 1504d6689ca9SLisandro Dalcin float version; 1505a8d4e440SJunchao Zhang int fileFormat; 1506d6689ca9SLisandro Dalcin 15079566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(gmsh, 1)); 15089566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(PETSC_COMM_SELF, &gmsh->viewer)); 15099566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(gmsh->viewer, PETSCVIEWERASCII)); 15109566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(gmsh->viewer, FILE_MODE_READ)); 15119566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(gmsh->viewer, filename)); 1512d6689ca9SLisandro Dalcin /* Read only the first two lines of the Gmsh file */ 15139566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 15149566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$MeshFormat", line)); 15159566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 2)); 1516d6689ca9SLisandro Dalcin snum = sscanf(line, "%f %d", &version, &fileType); 1517a8d4e440SJunchao Zhang fileFormat = (int)roundf(version * 10); 151808401ef6SPierre Jolivet PetscCheck(snum == 2, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line); 1519a8d4e440SJunchao Zhang PetscCheck(fileFormat >= 22, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at least 2.2", (double)version); 15201dca8a05SBarry Smith PetscCheck((int)version != 3, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f not supported", (double)version); 1521a8d4e440SJunchao Zhang PetscCheck(fileFormat <= 41, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at most 4.1", (double)version); 15229566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&gmsh->viewer)); 1523d6689ca9SLisandro Dalcin } 15249566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&fileType, 1, MPI_INT, 0, comm)); 1525d6689ca9SLisandro Dalcin vtype = (fileType == 0) ? PETSCVIEWERASCII : PETSCVIEWERBINARY; 1526d6689ca9SLisandro Dalcin 1527d6689ca9SLisandro Dalcin /* Create appropriate viewer and build plex */ 15289566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 15299566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, vtype)); 15309566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 15319566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 15329566063dSJacob Faibussowitsch PetscCall(DMPlexCreateGmsh(comm, viewer, interpolate, dm)); 15339566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 15343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1535d6689ca9SLisandro Dalcin } 1536d6689ca9SLisandro Dalcin 1537331830f3SMatthew G. Knepley /*@ 1538a1cb98faSBarry Smith DMPlexCreateGmsh - Create a `DMPLEX` mesh from a Gmsh file viewer 1539331830f3SMatthew G. Knepley 1540d083f849SBarry Smith Collective 1541331830f3SMatthew G. Knepley 1542331830f3SMatthew G. Knepley Input Parameters: 1543331830f3SMatthew G. Knepley + comm - The MPI communicator 1544a1cb98faSBarry Smith . viewer - The `PetscViewer` associated with a Gmsh file 1545331830f3SMatthew G. Knepley - interpolate - Create faces and edges in the mesh 1546331830f3SMatthew G. Knepley 1547331830f3SMatthew G. Knepley Output Parameter: 1548a1cb98faSBarry Smith . dm - The `DM` object representing the mesh 1549331830f3SMatthew G. Knepley 1550a1cb98faSBarry Smith Options Database Keys: 1551df93260fSMatthew G. Knepley + -dm_plex_gmsh_hybrid - Force triangular prisms to use tensor order 1552df93260fSMatthew G. Knepley . -dm_plex_gmsh_periodic - Read Gmsh periodic section and construct a periodic Plex 1553df93260fSMatthew G. Knepley . -dm_plex_gmsh_highorder - Generate high-order coordinates 1554df93260fSMatthew 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 15552b205333SMatthew G. Knepley . -dm_plex_gmsh_use_generic - Generate generic labels, i.e. Cell Sets, Face Sets, etc. 1556df93260fSMatthew G. Knepley . -dm_plex_gmsh_use_regions - Generate labels with region names 1557df93260fSMatthew G. Knepley . -dm_plex_gmsh_mark_vertices - Add vertices to generated labels 15584c375d72SMatthew G. Knepley . -dm_plex_gmsh_mark_vertices_strict - Add vertices included in a region to generated labels 1559df93260fSMatthew G. Knepley . -dm_plex_gmsh_multiple_tags - Allow multiple tags for default labels 1560df93260fSMatthew G. Knepley - -dm_plex_gmsh_spacedim <d> - Embedding space dimension, if different from topological dimension 1561df93260fSMatthew G. Knepley 15621d27aa22SBarry Smith Level: beginner 15631d27aa22SBarry Smith 15641d27aa22SBarry Smith Notes: 15651d27aa22SBarry Smith The Gmsh file format is described in <http://gmsh.info/doc/texinfo/gmsh.html#MSH-file-format> 1566df93260fSMatthew G. Knepley 15676497c311SBarry Smith By default, the "Cell Sets", "Face Sets", and "Vertex Sets" labels are created, and only insert the first tag on a point. By using `-dm_plex_gmsh_multiple_tags`, all tags can be inserted. Alternatively, `-dm_plex_gmsh_use_regions` creates labels based on the region names from the `PhysicalNames` section, and all tags are used, but you can retain the generic labels using `-dm_plex_gmsh_use_generic`. 1568331830f3SMatthew G. Knepley 15691cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()` 1570331830f3SMatthew G. Knepley @*/ 1571d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateGmsh(MPI_Comm comm, PetscViewer viewer, PetscBool interpolate, DM *dm) 1572d71ae5a4SJacob Faibussowitsch { 15730598e1a2SLisandro Dalcin GmshMesh *mesh = NULL; 157411c56cb0SLisandro Dalcin PetscViewer parentviewer = NULL; 15750598e1a2SLisandro Dalcin PetscBT periodicVerts = NULL; 1576eae3dc7dSJacob Faibussowitsch PetscBT *periodicCells = NULL; 15776858538eSMatthew G. Knepley DM cdm, cdmCell = NULL; 15786858538eSMatthew G. Knepley PetscSection cs, csCell = NULL; 15796858538eSMatthew G. Knepley Vec coordinates, coordinatesCell; 15800444adf6SMatthew G. Knepley DMLabel cellSets = NULL, faceSets = NULL, edgeSets = NULL, vertSets = NULL, marker = NULL, *regionSets; 15819db5b827SMatthew G. Knepley PetscInt dim = 0, coordDim = -1, order = 0, maxHeight = 0; 15829db5b827SMatthew G. Knepley PetscInt numNodes = 0, numElems = 0, numVerts = 0, numCells = 0, vStart, vEnd; 1583066ea43fSLisandro Dalcin PetscInt cell, cone[8], e, n, v, d; 15844c375d72SMatthew G. Knepley PetscBool usegeneric = PETSC_TRUE, useregions = PETSC_FALSE, markvertices = PETSC_FALSE, markverticesstrict = PETSC_FALSE, multipleTags = PETSC_FALSE; 15852b205333SMatthew G. Knepley PetscBool flg, binary, hybrid = interpolate, periodic = PETSC_TRUE; 1586066ea43fSLisandro Dalcin PetscBool highOrder = PETSC_TRUE, highOrderSet, project = PETSC_FALSE; 1587066ea43fSLisandro Dalcin PetscBool isSimplex = PETSC_FALSE, isHybrid = PETSC_FALSE, hasTetra = PETSC_FALSE; 15880598e1a2SLisandro Dalcin PetscMPIInt rank; 1589331830f3SMatthew G. Knepley 1590331830f3SMatthew G. Knepley PetscFunctionBegin; 15919566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1592d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)viewer); 1593d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Gmsh options"); 1594df93260fSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_gmsh_hybrid", "Force triangular prisms to use tensor order", "DMPlexCreateGmsh", hybrid, &hybrid, NULL)); 15959566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_periodic", "Read Gmsh periodic section", "DMPlexCreateGmsh", periodic, &periodic, NULL)); 15969566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_highorder", "Generate high-order coordinates", "DMPlexCreateGmsh", highOrder, &highOrder, &highOrderSet)); 15979566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_project", "Project high-order coordinates to a different space", "DMPlexCreateGmsh", project, &project, NULL)); 15989566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_use_regions", "Generate labels with region names", "DMPlexCreateGmsh", useregions, &useregions, NULL)); 15992b205333SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_gmsh_use_generic", "Generate generic labels, i.e. Cell Sets, Face Sets, etc", "DMPlexCreateGmsh", usegeneric, &usegeneric, &flg)); 16002b205333SMatthew G. Knepley if (!flg && useregions) usegeneric = PETSC_FALSE; 16019566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_mark_vertices", "Add vertices to generated labels", "DMPlexCreateGmsh", markvertices, &markvertices, NULL)); 16024c375d72SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_gmsh_mark_vertices_strict", "Add only directly tagged vertices to generated labels", "DMPlexCreateGmsh", markverticesstrict, &markverticesstrict, NULL)); 1603df93260fSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_gmsh_multiple_tags", "Allow multiple tags for default labels", "DMPlexCreateGmsh", multipleTags, &multipleTags, NULL)); 16049566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_gmsh_spacedim", "Embedding space dimension", "DMPlexCreateGmsh", coordDim, &coordDim, NULL, PETSC_DECIDE)); 16059db5b827SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_localize_height", "Localize edges and faces in addition to cells", "", maxHeight, &maxHeight, NULL, 0)); 1606d0609cedSBarry Smith PetscOptionsHeadEnd(); 1607d0609cedSBarry Smith PetscOptionsEnd(); 16080598e1a2SLisandro Dalcin 16099566063dSJacob Faibussowitsch PetscCall(GmshCellInfoSetUp()); 161011c56cb0SLisandro Dalcin 16119566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 16129566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 16139566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CreateGmsh, *dm, NULL, NULL, NULL)); 161411c56cb0SLisandro Dalcin 16159566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &binary)); 161611c56cb0SLisandro Dalcin 161711c56cb0SLisandro Dalcin /* Binary viewers read on all ranks, get subviewer to read only in rank 0 */ 16183b46f529SLisandro Dalcin if (binary) { 161911c56cb0SLisandro Dalcin parentviewer = viewer; 16209566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(parentviewer, PETSC_COMM_SELF, &viewer)); 162111c56cb0SLisandro Dalcin } 162211c56cb0SLisandro Dalcin 1623dd400576SPatrick Sanan if (rank == 0) { 16240598e1a2SLisandro Dalcin GmshFile gmsh[1]; 1625698a79b9SLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 1626698a79b9SLisandro Dalcin PetscBool match; 1627331830f3SMatthew G. Knepley 16289566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(gmsh, 1)); 1629698a79b9SLisandro Dalcin gmsh->viewer = viewer; 1630698a79b9SLisandro Dalcin gmsh->binary = binary; 1631698a79b9SLisandro Dalcin 16329566063dSJacob Faibussowitsch PetscCall(GmshMeshCreate(&mesh)); 16330598e1a2SLisandro Dalcin 1634698a79b9SLisandro Dalcin /* Read mesh format */ 16359566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 16369566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$MeshFormat", line)); 16379566063dSJacob Faibussowitsch PetscCall(GmshReadMeshFormat(gmsh)); 16389566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndMeshFormat", line)); 163911c56cb0SLisandro Dalcin 16408749820aSMatthew G. Knepley /* OPTIONAL Read mesh version (Neper only) */ 16419566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 16428749820aSMatthew G. Knepley PetscCall(GmshMatch(gmsh, "$MeshVersion", line, &match)); 16438749820aSMatthew G. Knepley if (match) { 16448749820aSMatthew G. Knepley PetscCall(GmshExpect(gmsh, "$MeshVersion", line)); 16458749820aSMatthew G. Knepley PetscCall(GmshReadMeshVersion(gmsh)); 16468749820aSMatthew G. Knepley PetscCall(GmshReadEndSection(gmsh, "$EndMeshVersion", line)); 16478749820aSMatthew G. Knepley /* Initial read for entity section */ 16488749820aSMatthew G. Knepley PetscCall(GmshReadSection(gmsh, line)); 16498749820aSMatthew G. Knepley } 16508749820aSMatthew G. Knepley 16518749820aSMatthew G. Knepley /* OPTIONAL Read mesh domain (Neper only) */ 16528749820aSMatthew G. Knepley PetscCall(GmshMatch(gmsh, "$Domain", line, &match)); 16538749820aSMatthew G. Knepley if (match) { 16548749820aSMatthew G. Knepley PetscCall(GmshExpect(gmsh, "$Domain", line)); 16558749820aSMatthew G. Knepley PetscCall(GmshReadMeshDomain(gmsh)); 16568749820aSMatthew G. Knepley PetscCall(GmshReadEndSection(gmsh, "$EndDomain", line)); 16578749820aSMatthew G. Knepley /* Initial read for entity section */ 16588749820aSMatthew G. Knepley PetscCall(GmshReadSection(gmsh, line)); 16598749820aSMatthew G. Knepley } 16608749820aSMatthew G. Knepley 16618749820aSMatthew G. Knepley /* OPTIONAL Read physical names */ 16629566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, "$PhysicalNames", line, &match)); 1663dc0ede3bSMatthew G. Knepley if (match) { 16649566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$PhysicalNames", line)); 16659566063dSJacob Faibussowitsch PetscCall(GmshReadPhysicalNames(gmsh, mesh)); 16669566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndPhysicalNames", line)); 1667698a79b9SLisandro Dalcin /* Initial read for entity section */ 16689566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 1669dc0ede3bSMatthew G. Knepley } 167011c56cb0SLisandro Dalcin 1671e43c9757SMatthew G. Knepley /* OPTIONAL Read entities */ 1672698a79b9SLisandro Dalcin if (gmsh->fileFormat >= 40) { 1673e43c9757SMatthew G. Knepley PetscCall(GmshMatch(gmsh, "$Entities", line, &match)); 1674e43c9757SMatthew G. Knepley if (match) { 16759566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$Entities", line)); 16769566063dSJacob Faibussowitsch PetscCall(GmshReadEntities(gmsh, mesh)); 16779566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndEntities", line)); 1678698a79b9SLisandro Dalcin /* Initial read for nodes section */ 16799566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 1680de78e4feSLisandro Dalcin } 1681e43c9757SMatthew G. Knepley } 1682de78e4feSLisandro Dalcin 1683698a79b9SLisandro Dalcin /* Read nodes */ 16849566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$Nodes", line)); 16859566063dSJacob Faibussowitsch PetscCall(GmshReadNodes(gmsh, mesh)); 16869566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndNodes", line)); 168711c56cb0SLisandro Dalcin 1688698a79b9SLisandro Dalcin /* Read elements */ 16899566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 16909566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$Elements", line)); 16919566063dSJacob Faibussowitsch PetscCall(GmshReadElements(gmsh, mesh)); 16929566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndElements", line)); 1693de78e4feSLisandro Dalcin 16940598e1a2SLisandro Dalcin /* Read periodic section (OPTIONAL) */ 1695698a79b9SLisandro Dalcin if (periodic) { 16969566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 16979566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, "$Periodic", line, &periodic)); 1698ef12879bSLisandro Dalcin } 1699ef12879bSLisandro Dalcin if (periodic) { 17009566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$Periodic", line)); 17019566063dSJacob Faibussowitsch PetscCall(GmshReadPeriodic(gmsh, mesh)); 17029566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndPeriodic", line)); 1703698a79b9SLisandro Dalcin } 1704698a79b9SLisandro Dalcin 17059566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->wbuf)); 17069566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->sbuf)); 17079566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->nbuf)); 17080598e1a2SLisandro Dalcin 17090598e1a2SLisandro Dalcin dim = mesh->dim; 1710066ea43fSLisandro Dalcin order = mesh->order; 17110598e1a2SLisandro Dalcin numNodes = mesh->numNodes; 17120598e1a2SLisandro Dalcin numElems = mesh->numElems; 17130598e1a2SLisandro Dalcin numVerts = mesh->numVerts; 17140598e1a2SLisandro Dalcin numCells = mesh->numCells; 1715066ea43fSLisandro Dalcin 1716066ea43fSLisandro Dalcin { 1717066ea43fSLisandro Dalcin GmshElement *elemA = mesh->numCells > 0 ? mesh->elements : NULL; 17188e3a54c0SPierre Jolivet GmshElement *elemB = PetscSafePointerPlusOffset(elemA, mesh->numCells - 1); 1719066ea43fSLisandro Dalcin int ptA = elemA ? GmshCellMap[elemA->cellType].polytope : -1; 1720066ea43fSLisandro Dalcin int ptB = elemB ? GmshCellMap[elemB->cellType].polytope : -1; 1721066ea43fSLisandro Dalcin isSimplex = (ptA == GMSH_QUA || ptA == GMSH_HEX) ? PETSC_FALSE : PETSC_TRUE; 1722066ea43fSLisandro Dalcin isHybrid = (ptA == ptB) ? PETSC_FALSE : PETSC_TRUE; 1723066ea43fSLisandro Dalcin hasTetra = (ptA == GMSH_TET) ? PETSC_TRUE : PETSC_FALSE; 1724066ea43fSLisandro Dalcin } 1725698a79b9SLisandro Dalcin } 1726698a79b9SLisandro Dalcin 172748a46eb9SPierre Jolivet if (parentviewer) PetscCall(PetscViewerRestoreSubViewer(parentviewer, PETSC_COMM_SELF, &viewer)); 1728698a79b9SLisandro Dalcin 1729066ea43fSLisandro Dalcin { 1730066ea43fSLisandro Dalcin int buf[6]; 1731698a79b9SLisandro Dalcin 1732066ea43fSLisandro Dalcin buf[0] = (int)dim; 1733066ea43fSLisandro Dalcin buf[1] = (int)order; 1734066ea43fSLisandro Dalcin buf[2] = periodic; 1735066ea43fSLisandro Dalcin buf[3] = isSimplex; 1736066ea43fSLisandro Dalcin buf[4] = isHybrid; 1737066ea43fSLisandro Dalcin buf[5] = hasTetra; 1738066ea43fSLisandro Dalcin 17399566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(buf, 6, MPI_INT, 0, comm)); 1740066ea43fSLisandro Dalcin 1741066ea43fSLisandro Dalcin dim = buf[0]; 1742066ea43fSLisandro Dalcin order = buf[1]; 1743066ea43fSLisandro Dalcin periodic = buf[2] ? PETSC_TRUE : PETSC_FALSE; 1744066ea43fSLisandro Dalcin isSimplex = buf[3] ? PETSC_TRUE : PETSC_FALSE; 1745066ea43fSLisandro Dalcin isHybrid = buf[4] ? PETSC_TRUE : PETSC_FALSE; 1746066ea43fSLisandro Dalcin hasTetra = buf[5] ? PETSC_TRUE : PETSC_FALSE; 1747dea2a3c7SStefano Zampini } 1748dea2a3c7SStefano Zampini 1749066ea43fSLisandro Dalcin if (!highOrderSet) highOrder = (order > 1) ? PETSC_TRUE : PETSC_FALSE; 175008401ef6SPierre Jolivet PetscCheck(!highOrder || !isHybrid, comm, PETSC_ERR_SUP, "No support for discretization on hybrid meshes yet"); 1751066ea43fSLisandro Dalcin 17520598e1a2SLisandro Dalcin /* We do not want this label automatically computed, instead we fill it here */ 17539566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "celltype")); 175411c56cb0SLisandro Dalcin 1755a4bb7517SMichael Lange /* Allocate the cell-vertex mesh */ 17569566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(*dm, 0, numCells + numVerts)); 17570598e1a2SLisandro Dalcin for (cell = 0; cell < numCells; ++cell) { 17580598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + cell; 17590598e1a2SLisandro Dalcin DMPolytopeType ctype = DMPolytopeTypeFromGmsh(elem->cellType); 17600598e1a2SLisandro Dalcin if (hybrid && hasTetra && ctype == DM_POLYTOPE_TRI_PRISM) ctype = DM_POLYTOPE_TRI_PRISM_TENSOR; 17619566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(*dm, cell, elem->numVerts)); 17629566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(*dm, cell, ctype)); 1763db397164SMichael Lange } 176448a46eb9SPierre Jolivet for (v = numCells; v < numCells + numVerts; ++v) PetscCall(DMPlexSetCellType(*dm, v, DM_POLYTOPE_POINT)); 17659566063dSJacob Faibussowitsch PetscCall(DMSetUp(*dm)); 176696ca5757SLisandro Dalcin 1767a4bb7517SMichael Lange /* Add cell-vertex connections */ 17680598e1a2SLisandro Dalcin for (cell = 0; cell < numCells; ++cell) { 17690598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + cell; 17700598e1a2SLisandro Dalcin for (v = 0; v < elem->numVerts; ++v) { 17710598e1a2SLisandro Dalcin const PetscInt nn = elem->nodes[v]; 17720598e1a2SLisandro Dalcin const PetscInt vv = mesh->vertexMap[nn]; 17730598e1a2SLisandro Dalcin cone[v] = numCells + vv; 1774db397164SMichael Lange } 17759566063dSJacob Faibussowitsch PetscCall(DMPlexReorderCell(*dm, cell, cone)); 17769566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(*dm, cell, cone)); 1777a4bb7517SMichael Lange } 177896ca5757SLisandro Dalcin 17799566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 17809566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(*dm)); 17819566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(*dm)); 1782331830f3SMatthew G. Knepley if (interpolate) { 17835fd9971aSMatthew G. Knepley DM idm; 1784331830f3SMatthew G. Knepley 17859566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 17869566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 1787331830f3SMatthew G. Knepley *dm = idm; 1788331830f3SMatthew G. Knepley } 17899db5b827SMatthew G. Knepley PetscCall(DMPlexGetDepthStratum(*dm, 0, &vStart, &vEnd)); 1790917266a4SLisandro Dalcin 1791dd400576SPatrick Sanan if (rank == 0) { 1792a45dabc8SMatthew G. Knepley const PetscInt Nr = useregions ? mesh->numRegions : 0; 1793d1a54cefSMatthew G. Knepley 17949566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(Nr, ®ionSets)); 17950598e1a2SLisandro Dalcin for (cell = 0, e = 0; e < numElems; ++e) { 17960598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + e; 17976e1dd89aSLawrence Mitchell 17986e1dd89aSLawrence Mitchell /* Create cell sets */ 17990598e1a2SLisandro Dalcin if (elem->dim == dim && dim > 0) { 18000598e1a2SLisandro Dalcin if (elem->numTags > 0) { 1801df93260fSMatthew G. Knepley PetscInt Nt = elem->numTags, t, r; 1802a45dabc8SMatthew G. Knepley 1803df93260fSMatthew G. Knepley for (t = 0; t < Nt; ++t) { 1804df93260fSMatthew G. Knepley const PetscInt tag = elem->tags[t]; 18052b205333SMatthew G. Knepley const PetscBool generic = usegeneric && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE; 1806df93260fSMatthew G. Knepley 1807df93260fSMatthew G. Knepley if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &cellSets, "Cell Sets", cell, tag)); 1808a45dabc8SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 1809df93260fSMatthew G. Knepley if (mesh->regionDims[r] != dim) continue; 18109566063dSJacob Faibussowitsch if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], cell, tag)); 1811a45dabc8SMatthew G. Knepley } 18126e1dd89aSLawrence Mitchell } 1813df93260fSMatthew G. Knepley } 1814917266a4SLisandro Dalcin cell++; 18156e1dd89aSLawrence Mitchell } 18160c070f12SSander Arens 18170598e1a2SLisandro Dalcin /* Create face sets */ 1818aec57b10SMatthew G. Knepley if (elem->numTags && interpolate && elem->dim == dim - 1) { 18190598e1a2SLisandro Dalcin PetscInt joinSize; 18200598e1a2SLisandro Dalcin const PetscInt *join = NULL; 18210444adf6SMatthew G. Knepley PetscInt Nt = elem->numTags, pdepth; 1822a45dabc8SMatthew G. Knepley 18230598e1a2SLisandro Dalcin /* Find the relevant facet with vertex joins */ 18240598e1a2SLisandro Dalcin for (v = 0; v < elem->numVerts; ++v) { 18250598e1a2SLisandro Dalcin const PetscInt nn = elem->nodes[v]; 18260598e1a2SLisandro Dalcin const PetscInt vv = mesh->vertexMap[nn]; 18270598e1a2SLisandro Dalcin cone[v] = vStart + vv; 18280598e1a2SLisandro Dalcin } 18299566063dSJacob Faibussowitsch PetscCall(DMPlexGetFullJoin(*dm, elem->numVerts, cone, &joinSize, &join)); 183063a3b9bcSJacob Faibussowitsch PetscCheck(joinSize == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Could not determine Plex facet for Gmsh element %" PetscInt_FMT " (Plex cell %" PetscInt_FMT ")", elem->id, e); 18310444adf6SMatthew G. Knepley PetscCall(DMPlexGetPointDepth(*dm, join[0], &pdepth)); 18320444adf6SMatthew G. Knepley PetscCheck(pdepth == dim - 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Plex facet %" PetscInt_FMT " for Gmsh element %" PetscInt_FMT " had depth %" PetscInt_FMT " != %" PetscInt_FMT, join[0], elem->id, pdepth, dim - 1); 18330444adf6SMatthew G. Knepley for (PetscInt t = 0; t < Nt; ++t) { 18345ad74b4fSMatthew G. Knepley const PetscInt tag = elem->tags[t]; 18352b205333SMatthew G. Knepley const PetscBool generic = usegeneric && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE; 18365ad74b4fSMatthew G. Knepley 1837df93260fSMatthew G. Knepley if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &faceSets, "Face Sets", join[0], tag)); 18380444adf6SMatthew G. Knepley for (PetscInt r = 0; r < Nr; ++r) { 1839df93260fSMatthew G. Knepley if (mesh->regionDims[r] != dim - 1) continue; 18409566063dSJacob Faibussowitsch if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], join[0], tag)); 1841a45dabc8SMatthew G. Knepley } 18425ad74b4fSMatthew G. Knepley } 18439566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(*dm, elem->numVerts, cone, &joinSize, &join)); 18440598e1a2SLisandro Dalcin } 18450598e1a2SLisandro Dalcin 1846aec57b10SMatthew G. Knepley /* Create edge sets */ 1847aec57b10SMatthew G. Knepley if (elem->numTags && interpolate && dim > 2 && elem->dim == 1) { 1848aec57b10SMatthew G. Knepley PetscInt joinSize; 1849aec57b10SMatthew G. Knepley const PetscInt *join = NULL; 1850aec57b10SMatthew G. Knepley PetscInt Nt = elem->numTags, t, r; 1851aec57b10SMatthew G. Knepley 1852aec57b10SMatthew G. Knepley /* Find the relevant edge with vertex joins */ 1853aec57b10SMatthew G. Knepley for (v = 0; v < elem->numVerts; ++v) { 1854aec57b10SMatthew G. Knepley const PetscInt nn = elem->nodes[v]; 1855aec57b10SMatthew G. Knepley const PetscInt vv = mesh->vertexMap[nn]; 1856aec57b10SMatthew G. Knepley cone[v] = vStart + vv; 1857aec57b10SMatthew G. Knepley } 1858aec57b10SMatthew G. Knepley PetscCall(DMPlexGetJoin(*dm, elem->numVerts, cone, &joinSize, &join)); 1859aec57b10SMatthew G. Knepley PetscCheck(joinSize == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Could not determine Plex edge for Gmsh element %" PetscInt_FMT " (Plex cell %" PetscInt_FMT ")", elem->id, e); 1860aec57b10SMatthew G. Knepley for (t = 0; t < Nt; ++t) { 1861aec57b10SMatthew G. Knepley const PetscInt tag = elem->tags[t]; 18622b205333SMatthew G. Knepley const PetscBool generic = usegeneric && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE; 1863aec57b10SMatthew G. Knepley 18640444adf6SMatthew G. Knepley if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &edgeSets, "Edge Sets", join[0], tag)); 1865aec57b10SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 1866aec57b10SMatthew G. Knepley if (mesh->regionDims[r] != 1) continue; 1867aec57b10SMatthew G. Knepley if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], join[0], tag)); 1868aec57b10SMatthew G. Knepley } 1869aec57b10SMatthew G. Knepley } 1870aec57b10SMatthew G. Knepley PetscCall(DMPlexRestoreJoin(*dm, elem->numVerts, cone, &joinSize, &join)); 1871aec57b10SMatthew G. Knepley } 1872aec57b10SMatthew G. Knepley 18730c070f12SSander Arens /* Create vertex sets */ 18744c375d72SMatthew G. Knepley if (elem->numTags && elem->dim == 0 && (markverticesstrict || markvertices)) { 18750598e1a2SLisandro Dalcin const PetscInt nn = elem->nodes[0]; 18760598e1a2SLisandro Dalcin const PetscInt vv = mesh->vertexMap[nn]; 1877*bb3f7942SBrad Aagaard PetscInt Nt = elem->numTags; 1878*bb3f7942SBrad Aagaard 1879*bb3f7942SBrad Aagaard for (PetscInt t = 0; t < Nt; ++t) { 1880*bb3f7942SBrad Aagaard const PetscInt tag = elem->tags[t]; 1881a45dabc8SMatthew G. Knepley 18828a3d9825SMatthew G. Knepley if (vv < 0) continue; 18832b205333SMatthew G. Knepley if (usegeneric) PetscCall(DMSetLabelValue_Fast(*dm, &vertSets, "Vertex Sets", vStart + vv, tag)); 1884*bb3f7942SBrad Aagaard for (PetscInt r = 0; r < Nr; ++r) { 1885df93260fSMatthew G. Knepley if (mesh->regionDims[r] != 0) continue; 18869566063dSJacob Faibussowitsch if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], vStart + vv, tag)); 188781a1af93SMatthew G. Knepley } 188881a1af93SMatthew G. Knepley } 188981a1af93SMatthew G. Knepley } 1890*bb3f7942SBrad Aagaard } 189181a1af93SMatthew G. Knepley if (markvertices) { 189281a1af93SMatthew G. Knepley for (v = 0; v < numNodes; ++v) { 189381a1af93SMatthew G. Knepley const PetscInt vv = mesh->vertexMap[v]; 18947d5b9244SMatthew G. Knepley const PetscInt *tags = &mesh->nodelist->tag[v * GMSH_MAX_TAGS]; 18957d5b9244SMatthew G. Knepley PetscInt r, t; 189681a1af93SMatthew G. Knepley 18978a3d9825SMatthew G. Knepley if (vv < 0) continue; 18987d5b9244SMatthew G. Knepley for (t = 0; t < GMSH_MAX_TAGS; ++t) { 18997d5b9244SMatthew G. Knepley const PetscInt tag = tags[t]; 19002b205333SMatthew G. Knepley const PetscBool generic = usegeneric && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE; 19017d5b9244SMatthew G. Knepley 19027d5b9244SMatthew G. Knepley if (tag == -1) continue; 1903df93260fSMatthew G. Knepley if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &vertSets, "Vertex Sets", vStart + vv, tag)); 1904a45dabc8SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 19059566063dSJacob Faibussowitsch if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], vStart + vv, tag)); 19060598e1a2SLisandro Dalcin } 19070598e1a2SLisandro Dalcin } 19080598e1a2SLisandro Dalcin } 19090598e1a2SLisandro Dalcin } 19109566063dSJacob Faibussowitsch PetscCall(PetscFree(regionSets)); 1911a45dabc8SMatthew G. Knepley } 19120598e1a2SLisandro Dalcin 19130444adf6SMatthew G. Knepley { /* Create Cell/Face/Edge/Vertex Sets labels at all processes */ 19149371c9d4SSatish Balay enum { 19150444adf6SMatthew G. Knepley n = 5 19169371c9d4SSatish Balay }; 19177dd454faSLisandro Dalcin PetscBool flag[n]; 19187dd454faSLisandro Dalcin 19197dd454faSLisandro Dalcin flag[0] = cellSets ? PETSC_TRUE : PETSC_FALSE; 19207dd454faSLisandro Dalcin flag[1] = faceSets ? PETSC_TRUE : PETSC_FALSE; 19210444adf6SMatthew G. Knepley flag[2] = edgeSets ? PETSC_TRUE : PETSC_FALSE; 19220444adf6SMatthew G. Knepley flag[3] = vertSets ? PETSC_TRUE : PETSC_FALSE; 19230444adf6SMatthew G. Knepley flag[4] = marker ? PETSC_TRUE : PETSC_FALSE; 19249566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(flag, n, MPIU_BOOL, 0, comm)); 19259566063dSJacob Faibussowitsch if (flag[0]) PetscCall(DMCreateLabel(*dm, "Cell Sets")); 19269566063dSJacob Faibussowitsch if (flag[1]) PetscCall(DMCreateLabel(*dm, "Face Sets")); 19270444adf6SMatthew G. Knepley if (flag[2]) PetscCall(DMCreateLabel(*dm, "Edge Sets")); 19280444adf6SMatthew G. Knepley if (flag[3]) PetscCall(DMCreateLabel(*dm, "Vertex Sets")); 19290444adf6SMatthew G. Knepley if (flag[4]) PetscCall(DMCreateLabel(*dm, "marker")); 19307dd454faSLisandro Dalcin } 19317dd454faSLisandro Dalcin 19320598e1a2SLisandro Dalcin if (periodic) { 19339566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(numVerts, &periodicVerts)); 19340598e1a2SLisandro Dalcin for (n = 0; n < numNodes; ++n) { 19350598e1a2SLisandro Dalcin if (mesh->vertexMap[n] >= 0) { 19360598e1a2SLisandro Dalcin if (PetscUnlikely(mesh->periodMap[n] != n)) { 19370598e1a2SLisandro Dalcin PetscInt m = mesh->periodMap[n]; 19389566063dSJacob Faibussowitsch PetscCall(PetscBTSet(periodicVerts, mesh->vertexMap[n])); 19399566063dSJacob Faibussowitsch PetscCall(PetscBTSet(periodicVerts, mesh->vertexMap[m])); 19400598e1a2SLisandro Dalcin } 19410598e1a2SLisandro Dalcin } 19420598e1a2SLisandro Dalcin } 19439db5b827SMatthew G. Knepley PetscCall(DMGetCoordinateDM(*dm, &cdm)); 1944eae3dc7dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxHeight + 1, &periodicCells)); 19459db5b827SMatthew G. Knepley for (PetscInt h = 0; h <= maxHeight; ++h) { 19469db5b827SMatthew G. Knepley PetscInt pStart, pEnd; 19479db5b827SMatthew G. Knepley 19489db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(*dm, h, &pStart, &pEnd)); 19499db5b827SMatthew G. Knepley PetscCall(PetscBTCreate(pEnd - pStart, &periodicCells[h])); 19509db5b827SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 19519db5b827SMatthew G. Knepley PetscInt *closure = NULL; 19529db5b827SMatthew G. Knepley PetscInt Ncl; 19539db5b827SMatthew G. Knepley 19549db5b827SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure)); 19559db5b827SMatthew G. Knepley for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) { 19569db5b827SMatthew G. Knepley if (closure[cl] >= vStart && closure[cl] < vEnd) { 19579db5b827SMatthew G. Knepley if (PetscUnlikely(PetscBTLookup(periodicVerts, closure[cl] - vStart))) { 19589db5b827SMatthew G. Knepley PetscCall(PetscBTSet(periodicCells[h], p - pStart)); 19599371c9d4SSatish Balay break; 19600c070f12SSander Arens } 19610c070f12SSander Arens } 19620c070f12SSander Arens } 19639db5b827SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure)); 19649db5b827SMatthew G. Knepley } 19659db5b827SMatthew G. Knepley } 196616ad7e67SMichael Lange } 196716ad7e67SMichael Lange 1968066ea43fSLisandro Dalcin /* Setup coordinate DM */ 19690598e1a2SLisandro Dalcin if (coordDim < 0) coordDim = dim; 19709566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(*dm, coordDim)); 19719566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(*dm, &cdm)); 1972066ea43fSLisandro Dalcin if (highOrder) { 1973066ea43fSLisandro Dalcin PetscFE fe; 1974066ea43fSLisandro Dalcin PetscBool continuity = periodic ? PETSC_FALSE : PETSC_TRUE; 1975066ea43fSLisandro Dalcin PetscDTNodeType nodeType = PETSCDTNODES_EQUISPACED; 1976066ea43fSLisandro Dalcin 1977066ea43fSLisandro Dalcin if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */ 1978066ea43fSLisandro Dalcin 19799566063dSJacob Faibussowitsch PetscCall(GmshCreateFE(comm, NULL, isSimplex, continuity, nodeType, dim, coordDim, order, &fe)); 19809566063dSJacob Faibussowitsch PetscCall(PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_fe_view")); 19819566063dSJacob Faibussowitsch PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)fe)); 19829566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 19839566063dSJacob Faibussowitsch PetscCall(DMCreateDS(cdm)); 1984066ea43fSLisandro Dalcin } 19856858538eSMatthew G. Knepley if (periodic) { 19866858538eSMatthew G. Knepley PetscCall(DMClone(cdm, &cdmCell)); 19876858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(*dm, cdmCell)); 19886858538eSMatthew G. Knepley } 1989066ea43fSLisandro Dalcin 1990066ea43fSLisandro Dalcin /* Create coordinates */ 1991066ea43fSLisandro Dalcin if (highOrder) { 1992066ea43fSLisandro Dalcin PetscInt maxDof = GmshNumNodes_HEX(order) * coordDim; 1993066ea43fSLisandro Dalcin double *coords = mesh ? mesh->nodelist->xyz : NULL; 1994066ea43fSLisandro Dalcin PetscSection section; 1995066ea43fSLisandro Dalcin PetscScalar *cellCoords; 1996066ea43fSLisandro Dalcin 19979566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(cdm, NULL)); 19986858538eSMatthew G. Knepley PetscCall(DMGetLocalSection(cdm, &cs)); 19996858538eSMatthew G. Knepley PetscCall(PetscSectionClone(cs, §ion)); 20009566063dSJacob Faibussowitsch PetscCall(DMPlexSetClosurePermutationTensor(cdm, 0, section)); /* XXX Implement DMPlexSetClosurePermutationLexicographic() */ 2001066ea43fSLisandro Dalcin 20029566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(cdm, &coordinates)); 20039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof, &cellCoords)); 2004066ea43fSLisandro Dalcin for (cell = 0; cell < numCells; ++cell) { 2005066ea43fSLisandro Dalcin GmshElement *elem = mesh->elements + cell; 2006066ea43fSLisandro Dalcin const int *lexorder = GmshCellMap[elem->cellType].lexorder(); 2007b9bf55e5SMatthew G. Knepley int s = 0; 2008066ea43fSLisandro Dalcin for (n = 0; n < elem->numNodes; ++n) { 2009b9bf55e5SMatthew G. Knepley while (lexorder[n + s] < 0) ++s; 2010b9bf55e5SMatthew G. Knepley const PetscInt node = elem->nodes[lexorder[n + s]]; 2011b9bf55e5SMatthew G. Knepley for (d = 0; d < coordDim; ++d) cellCoords[(n + s) * coordDim + d] = (PetscReal)coords[node * 3 + d]; 2012b9bf55e5SMatthew G. Knepley } 2013b9bf55e5SMatthew G. Knepley if (s) { 2014b9bf55e5SMatthew G. Knepley /* For the coordinate mapping we weight vertices by -1/4 and edges by 1/2, which we get from Q_2 interpolation */ 2015b9bf55e5SMatthew G. Knepley PetscReal quaCenterWeights[9] = {-0.25, 0.5, -0.25, 0.5, 0.0, 0.5, -0.25, 0.5, -0.25}; 2016b9bf55e5SMatthew G. Knepley /* For the coordinate mapping we weight vertices by -1/4 and edges by 1/2, which we get from Q_2 interpolation */ 20179371c9d4SSatish 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}; 20189371c9d4SSatish 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}; 20199371c9d4SSatish 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}; 20209371c9d4SSatish 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}; 20219371c9d4SSatish 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}; 20229371c9d4SSatish 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}; 20239371c9d4SSatish 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}; 2024b9bf55e5SMatthew G. Knepley PetscReal *sdWeights2[9] = {NULL, NULL, NULL, NULL, quaCenterWeights, NULL, NULL, NULL, NULL}; 20259371c9d4SSatish Balay PetscReal *sdWeights3[27] = {NULL, NULL, NULL, NULL, hexBottomWeights, NULL, NULL, NULL, NULL, NULL, hexFrontWeights, NULL, hexLeftWeights, hexCenterWeights, hexRightWeights, NULL, hexBackWeights, NULL, 2026b9bf55e5SMatthew G. Knepley NULL, NULL, NULL, NULL, hexTopWeights, NULL, NULL, NULL, NULL}; 2027b9bf55e5SMatthew G. Knepley PetscReal **sdWeights[4] = {NULL, NULL, sdWeights2, sdWeights3}; 2028b9bf55e5SMatthew G. Knepley 2029b9bf55e5SMatthew G. Knepley /* Missing entries in serendipity cell, only works for 8-node quad and 20-node hex */ 2030b9bf55e5SMatthew G. Knepley for (n = 0; n < elem->numNodes + s; ++n) { 2031b9bf55e5SMatthew G. Knepley if (lexorder[n] >= 0) continue; 2032b9bf55e5SMatthew G. Knepley for (d = 0; d < coordDim; ++d) cellCoords[n * coordDim + d] = 0.0; 2033b9bf55e5SMatthew G. Knepley for (int bn = 0; bn < elem->numNodes + s; ++bn) { 2034b9bf55e5SMatthew G. Knepley if (lexorder[bn] < 0) continue; 2035b9bf55e5SMatthew G. Knepley const PetscReal *weights = sdWeights[coordDim][n]; 2036b9bf55e5SMatthew G. Knepley const PetscInt bnode = elem->nodes[lexorder[bn]]; 2037b9bf55e5SMatthew G. Knepley for (d = 0; d < coordDim; ++d) cellCoords[n * coordDim + d] += weights[bn] * (PetscReal)coords[bnode * 3 + d]; 2038b9bf55e5SMatthew G. Knepley } 2039b9bf55e5SMatthew G. Knepley } 2040066ea43fSLisandro Dalcin } 20419566063dSJacob Faibussowitsch PetscCall(DMPlexVecSetClosure(cdm, section, coordinates, cell, cellCoords, INSERT_VALUES)); 2042066ea43fSLisandro Dalcin } 20439566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 20449566063dSJacob Faibussowitsch PetscCall(PetscFree(cellCoords)); 2045066ea43fSLisandro Dalcin } else { 2046066ea43fSLisandro Dalcin PetscInt *nodeMap; 2047066ea43fSLisandro Dalcin double *coords = mesh ? mesh->nodelist->xyz : NULL; 2048066ea43fSLisandro Dalcin PetscScalar *pointCoords; 2049066ea43fSLisandro Dalcin 20506858538eSMatthew G. Knepley PetscCall(DMGetCoordinateSection(*dm, &cs)); 20516858538eSMatthew G. Knepley PetscCall(PetscSectionSetNumFields(cs, 1)); 20526858538eSMatthew G. Knepley PetscCall(PetscSectionSetFieldComponents(cs, 0, coordDim)); 20536858538eSMatthew G. Knepley PetscCall(PetscSectionSetChart(cs, numCells, numCells + numVerts)); 20546858538eSMatthew G. Knepley for (v = numCells; v < numCells + numVerts; ++v) { 20556858538eSMatthew G. Knepley PetscCall(PetscSectionSetDof(cs, v, coordDim)); 20566858538eSMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(cs, v, 0, coordDim)); 2057f45c9589SStefano Zampini } 20586858538eSMatthew G. Knepley PetscCall(PetscSectionSetUp(cs)); 20596858538eSMatthew G. Knepley 20606858538eSMatthew G. Knepley /* We need to localize coordinates on cells */ 20610598e1a2SLisandro Dalcin if (periodic) { 20621690c2aeSBarry Smith PetscInt newStart = PETSC_INT_MAX, newEnd = -1, pStart, pEnd; 20639db5b827SMatthew G. Knepley 20646858538eSMatthew G. Knepley PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)cdmCell), &csCell)); 20656858538eSMatthew G. Knepley PetscCall(PetscSectionSetNumFields(csCell, 1)); 20666858538eSMatthew G. Knepley PetscCall(PetscSectionSetFieldComponents(csCell, 0, coordDim)); 20679db5b827SMatthew G. Knepley for (PetscInt h = 0; h <= maxHeight; h++) { 20689db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(cdmCell, h, &pStart, &pEnd)); 20699db5b827SMatthew G. Knepley newStart = PetscMin(newStart, pStart); 20709db5b827SMatthew G. Knepley newEnd = PetscMax(newEnd, pEnd); 20719db5b827SMatthew G. Knepley } 20729db5b827SMatthew G. Knepley PetscCall(PetscSectionSetChart(csCell, newStart, newEnd)); 20739db5b827SMatthew G. Knepley for (PetscInt h = 0; h <= maxHeight; h++) { 20749db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(cdmCell, h, &pStart, &pEnd)); 20759db5b827SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 20769db5b827SMatthew G. Knepley PetscInt *closure = NULL; 20779db5b827SMatthew G. Knepley PetscInt Ncl, Nv = 0; 20786858538eSMatthew G. Knepley 20799db5b827SMatthew G. Knepley if (PetscUnlikely(PetscBTLookup(periodicCells[h], p - pStart))) { 20809db5b827SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure)); 20819db5b827SMatthew G. Knepley for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) { 20829db5b827SMatthew G. Knepley if (closure[cl] >= vStart && closure[cl] < vEnd) ++Nv; 20839db5b827SMatthew G. Knepley } 20849db5b827SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure)); 20859db5b827SMatthew G. Knepley PetscCall(PetscSectionSetDof(csCell, p, Nv * coordDim)); 20869db5b827SMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(csCell, p, 0, Nv * coordDim)); 20879db5b827SMatthew G. Knepley } 2088f45c9589SStefano Zampini } 2089f45c9589SStefano Zampini } 20906858538eSMatthew G. Knepley PetscCall(PetscSectionSetUp(csCell)); 20916858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateSection(*dm, PETSC_DETERMINE, csCell)); 2092f45c9589SStefano Zampini } 2093066ea43fSLisandro Dalcin 20949566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(cdm, &coordinates)); 20959566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &pointCoords)); 20966858538eSMatthew G. Knepley PetscCall(PetscMalloc1(numVerts, &nodeMap)); 20976858538eSMatthew G. Knepley for (n = 0; n < numNodes; n++) 20986858538eSMatthew G. Knepley if (mesh->vertexMap[n] >= 0) nodeMap[mesh->vertexMap[n]] = n; 20996858538eSMatthew G. Knepley for (v = 0; v < numVerts; ++v) { 21006858538eSMatthew G. Knepley PetscInt off, node = nodeMap[v]; 21016858538eSMatthew G. Knepley 21026858538eSMatthew G. Knepley PetscCall(PetscSectionGetOffset(cs, numCells + v, &off)); 21036858538eSMatthew G. Knepley for (d = 0; d < coordDim; ++d) pointCoords[off + d] = (PetscReal)coords[node * 3 + d]; 21046858538eSMatthew G. Knepley } 21056858538eSMatthew G. Knepley PetscCall(VecRestoreArray(coordinates, &pointCoords)); 21066858538eSMatthew G. Knepley 21070598e1a2SLisandro Dalcin if (periodic) { 21089db5b827SMatthew G. Knepley PetscInt cStart, cEnd; 21099db5b827SMatthew G. Knepley 21109db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(cdmCell, 0, &cStart, &cEnd)); 21116858538eSMatthew G. Knepley PetscCall(DMCreateLocalVector(cdmCell, &coordinatesCell)); 21126858538eSMatthew G. Knepley PetscCall(VecGetArray(coordinatesCell, &pointCoords)); 21139db5b827SMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) { 21149db5b827SMatthew G. Knepley GmshElement *elem = mesh->elements + c - cStart; 21159db5b827SMatthew G. Knepley PetscInt *closure = NULL; 21169db5b827SMatthew G. Knepley PetscInt verts[8]; 21179db5b827SMatthew G. Knepley PetscInt Ncl, Nv = 0; 21189db5b827SMatthew G. Knepley 21199db5b827SMatthew G. Knepley for (PetscInt v = 0; v < elem->numVerts; ++v) cone[v] = elem->nodes[v]; 21209db5b827SMatthew G. Knepley PetscCall(DMPlexReorderCell(cdmCell, c, cone)); 21219db5b827SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(cdmCell, c, PETSC_TRUE, &Ncl, &closure)); 21229db5b827SMatthew G. Knepley for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) { 21239db5b827SMatthew G. Knepley if (closure[cl] >= vStart && closure[cl] < vEnd) verts[Nv++] = closure[cl]; 2124331830f3SMatthew G. Knepley } 21259db5b827SMatthew 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); 21269db5b827SMatthew G. Knepley for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) { 21279db5b827SMatthew G. Knepley const PetscInt point = closure[cl]; 21289db5b827SMatthew G. Knepley PetscInt hStart, h; 21299db5b827SMatthew G. Knepley 21309db5b827SMatthew G. Knepley PetscCall(DMPlexGetPointHeight(cdmCell, point, &h)); 21319db5b827SMatthew G. Knepley if (h > maxHeight) continue; 21329db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(cdmCell, h, &hStart, NULL)); 21339db5b827SMatthew G. Knepley if (PetscUnlikely(PetscBTLookup(periodicCells[h], point - hStart))) { 21349db5b827SMatthew G. Knepley PetscInt *pclosure = NULL; 21359db5b827SMatthew G. Knepley PetscInt Npcl, off, v; 21369db5b827SMatthew G. Knepley 21379db5b827SMatthew G. Knepley PetscCall(PetscSectionGetOffset(csCell, point, &off)); 21389db5b827SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(cdmCell, point, PETSC_TRUE, &Npcl, &pclosure)); 21399db5b827SMatthew G. Knepley for (PetscInt pcl = 0; pcl < Npcl * 2; pcl += 2) { 21409db5b827SMatthew G. Knepley if (pclosure[pcl] >= vStart && pclosure[pcl] < vEnd) { 21419db5b827SMatthew G. Knepley for (v = 0; v < Nv; ++v) 21429db5b827SMatthew G. Knepley if (verts[v] == pclosure[pcl]) break; 21439db5b827SMatthew 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); 21449db5b827SMatthew G. Knepley for (PetscInt d = 0; d < coordDim; ++d) pointCoords[off++] = (PetscReal)coords[cone[v] * 3 + d]; 21459db5b827SMatthew G. Knepley ++v; 21469db5b827SMatthew G. Knepley } 21479db5b827SMatthew G. Knepley } 21489db5b827SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(cdmCell, point, PETSC_TRUE, &Npcl, &pclosure)); 21499db5b827SMatthew G. Knepley } 21509db5b827SMatthew G. Knepley } 21519db5b827SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(cdmCell, c, PETSC_TRUE, &Ncl, &closure)); 2152331830f3SMatthew G. Knepley } 21536858538eSMatthew G. Knepley PetscCall(VecSetBlockSize(coordinatesCell, coordDim)); 21546858538eSMatthew G. Knepley PetscCall(VecRestoreArray(coordinatesCell, &pointCoords)); 21556858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(*dm, coordinatesCell)); 21566858538eSMatthew G. Knepley PetscCall(VecDestroy(&coordinatesCell)); 2157331830f3SMatthew G. Knepley } 21589db5b827SMatthew G. Knepley PetscCall(PetscFree(nodeMap)); 21596858538eSMatthew G. Knepley PetscCall(PetscSectionDestroy(&csCell)); 21606858538eSMatthew G. Knepley PetscCall(DMDestroy(&cdmCell)); 2161066ea43fSLisandro Dalcin } 2162066ea43fSLisandro Dalcin 21639566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 21649566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, coordDim)); 21659566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(*dm, coordinates)); 21669566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 216711c56cb0SLisandro Dalcin 21689566063dSJacob Faibussowitsch PetscCall(GmshMeshDestroy(&mesh)); 21699566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&periodicVerts)); 2170eae3dc7dSJacob Faibussowitsch if (periodic) { 2171eae3dc7dSJacob Faibussowitsch for (PetscInt h = 0; h <= maxHeight; ++h) PetscCall(PetscBTDestroy(periodicCells + h)); 2172eae3dc7dSJacob Faibussowitsch PetscCall(PetscFree(periodicCells)); 2173eae3dc7dSJacob Faibussowitsch } 217411c56cb0SLisandro Dalcin 2175066ea43fSLisandro Dalcin if (highOrder && project) { 2176066ea43fSLisandro Dalcin PetscFE fe; 2177066ea43fSLisandro Dalcin const char prefix[] = "dm_plex_gmsh_project_"; 2178066ea43fSLisandro Dalcin PetscBool continuity = periodic ? PETSC_FALSE : PETSC_TRUE; 2179066ea43fSLisandro Dalcin PetscDTNodeType nodeType = PETSCDTNODES_GAUSSJACOBI; 2180066ea43fSLisandro Dalcin 2181066ea43fSLisandro Dalcin if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */ 21829566063dSJacob Faibussowitsch PetscCall(GmshCreateFE(comm, prefix, isSimplex, continuity, nodeType, dim, coordDim, order, &fe)); 21839566063dSJacob Faibussowitsch PetscCall(PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_project_fe_view")); 2184e44f6aebSMatthew G. Knepley PetscCall(DMSetCoordinateDisc(*dm, fe, PETSC_TRUE)); 21859566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 2186066ea43fSLisandro Dalcin } 2187066ea43fSLisandro Dalcin 21889566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CreateGmsh, *dm, NULL, NULL, NULL)); 21893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2190331830f3SMatthew G. Knepley } 2191