1331830f3SMatthew G. Knepley #define PETSCDM_DLL 2af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 3730356f6SLisandro Dalcin #include <petsc/private/hashmapi.h> 4331830f3SMatthew G. Knepley 5066ea43fSLisandro Dalcin #include <../src/dm/impls/plex/gmshlex.h> 6066ea43fSLisandro Dalcin 7066ea43fSLisandro Dalcin #define GMSH_LEXORDER_ITEM(T, p) \ 8d71ae5a4SJacob Faibussowitsch static int *GmshLexOrder_##T##_##p(void) \ 9d71ae5a4SJacob Faibussowitsch { \ 10066ea43fSLisandro Dalcin static int Gmsh_LexOrder_##T##_##p[GmshNumNodes_##T(p)] = {-1}; \ 11066ea43fSLisandro Dalcin int *lex = Gmsh_LexOrder_##T##_##p; \ 12066ea43fSLisandro Dalcin if (lex[0] == -1) (void)GmshLexOrder_##T(p, lex, 0); \ 13066ea43fSLisandro Dalcin return lex; \ 14066ea43fSLisandro Dalcin } 15066ea43fSLisandro Dalcin 16d71ae5a4SJacob Faibussowitsch static int *GmshLexOrder_QUA_2_Serendipity(void) 17d71ae5a4SJacob Faibussowitsch { 18b9bf55e5SMatthew G. Knepley static int Gmsh_LexOrder_QUA_2_Serendipity[9] = {-1}; 19b9bf55e5SMatthew G. Knepley int *lex = Gmsh_LexOrder_QUA_2_Serendipity; 20b9bf55e5SMatthew G. Knepley if (lex[0] == -1) { 21b9bf55e5SMatthew G. Knepley /* Vertices */ 229371c9d4SSatish Balay lex[0] = 0; 239371c9d4SSatish Balay lex[2] = 1; 249371c9d4SSatish Balay lex[8] = 2; 259371c9d4SSatish Balay lex[6] = 3; 26b9bf55e5SMatthew G. Knepley /* Edges */ 279371c9d4SSatish Balay lex[1] = 4; 289371c9d4SSatish Balay lex[5] = 5; 299371c9d4SSatish Balay lex[7] = 6; 309371c9d4SSatish Balay lex[3] = 7; 31b9bf55e5SMatthew G. Knepley /* Cell */ 32b9bf55e5SMatthew G. Knepley lex[4] = -8; 33b9bf55e5SMatthew G. Knepley } 34b9bf55e5SMatthew G. Knepley return lex; 35b9bf55e5SMatthew G. Knepley } 36b9bf55e5SMatthew G. Knepley 37d71ae5a4SJacob Faibussowitsch static int *GmshLexOrder_HEX_2_Serendipity(void) 38d71ae5a4SJacob Faibussowitsch { 39b9bf55e5SMatthew G. Knepley static int Gmsh_LexOrder_HEX_2_Serendipity[27] = {-1}; 40b9bf55e5SMatthew G. Knepley int *lex = Gmsh_LexOrder_HEX_2_Serendipity; 41b9bf55e5SMatthew G. Knepley if (lex[0] == -1) { 42b9bf55e5SMatthew G. Knepley /* Vertices */ 439371c9d4SSatish Balay lex[0] = 0; 449371c9d4SSatish Balay lex[2] = 1; 459371c9d4SSatish Balay lex[8] = 2; 469371c9d4SSatish Balay lex[6] = 3; 479371c9d4SSatish Balay lex[18] = 4; 489371c9d4SSatish Balay lex[20] = 5; 499371c9d4SSatish Balay lex[26] = 6; 509371c9d4SSatish Balay lex[24] = 7; 51b9bf55e5SMatthew G. Knepley /* Edges */ 529371c9d4SSatish Balay lex[1] = 8; 539371c9d4SSatish Balay lex[3] = 9; 549371c9d4SSatish Balay lex[9] = 10; 559371c9d4SSatish Balay lex[5] = 11; 569371c9d4SSatish Balay lex[11] = 12; 579371c9d4SSatish Balay lex[7] = 13; 589371c9d4SSatish Balay lex[17] = 14; 599371c9d4SSatish Balay lex[15] = 15; 609371c9d4SSatish Balay lex[19] = 16; 619371c9d4SSatish Balay lex[21] = 17; 629371c9d4SSatish Balay lex[23] = 18; 639371c9d4SSatish Balay lex[25] = 19; 64b9bf55e5SMatthew G. Knepley /* Faces */ 659371c9d4SSatish Balay lex[4] = -20; 669371c9d4SSatish Balay lex[10] = -21; 679371c9d4SSatish Balay lex[12] = -22; 689371c9d4SSatish Balay lex[14] = -23; 699371c9d4SSatish Balay lex[16] = -24; 709371c9d4SSatish Balay lex[22] = -25; 71b9bf55e5SMatthew G. Knepley /* Cell */ 72b9bf55e5SMatthew G. Knepley lex[13] = -26; 73b9bf55e5SMatthew G. Knepley } 74b9bf55e5SMatthew G. Knepley return lex; 75b9bf55e5SMatthew G. Knepley } 76b9bf55e5SMatthew G. Knepley 77066ea43fSLisandro Dalcin #define GMSH_LEXORDER_LIST(T) \ 78066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 1) \ 79066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 2) \ 80066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 3) \ 81066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 4) \ 82066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 5) \ 83066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 6) \ 84066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 7) \ 85066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 8) \ 86066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 9) \ 87066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 10) 88066ea43fSLisandro Dalcin 89066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(VTX, 0) 90066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(SEG) 91066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(TRI) 92066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(QUA) 93066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(TET) 94066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(HEX) 95066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(PRI) 96066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(PYR) 97066ea43fSLisandro Dalcin 98066ea43fSLisandro Dalcin typedef enum { 99066ea43fSLisandro Dalcin GMSH_VTX = 0, 100066ea43fSLisandro Dalcin GMSH_SEG = 1, 101066ea43fSLisandro Dalcin GMSH_TRI = 2, 102066ea43fSLisandro Dalcin GMSH_QUA = 3, 103066ea43fSLisandro Dalcin GMSH_TET = 4, 104066ea43fSLisandro Dalcin GMSH_HEX = 5, 105066ea43fSLisandro Dalcin GMSH_PRI = 6, 106066ea43fSLisandro Dalcin GMSH_PYR = 7, 107066ea43fSLisandro Dalcin GMSH_NUM_POLYTOPES = 8 108066ea43fSLisandro Dalcin } GmshPolytopeType; 109066ea43fSLisandro Dalcin 110de78e4feSLisandro Dalcin typedef struct { 1110598e1a2SLisandro Dalcin int cellType; 112066ea43fSLisandro Dalcin int polytope; 1130598e1a2SLisandro Dalcin int dim; 1140598e1a2SLisandro Dalcin int order; 115066ea43fSLisandro Dalcin int numVerts; 1160598e1a2SLisandro Dalcin int numNodes; 117066ea43fSLisandro Dalcin int *(*lexorder)(void); 1180598e1a2SLisandro Dalcin } GmshCellInfo; 1190598e1a2SLisandro Dalcin 120066ea43fSLisandro Dalcin #define GmshCellEntry(cellType, polytope, dim, order) \ 121d71ae5a4SJacob Faibussowitsch { \ 122d71ae5a4SJacob Faibussowitsch cellType, GMSH_##polytope, dim, order, GmshNumNodes_##polytope(1), GmshNumNodes_##polytope(order), GmshLexOrder_##polytope##_##order \ 123d71ae5a4SJacob Faibussowitsch } 1240598e1a2SLisandro Dalcin 1250598e1a2SLisandro Dalcin static const GmshCellInfo GmshCellTable[] = { 126066ea43fSLisandro Dalcin GmshCellEntry(15, VTX, 0, 0), 1270598e1a2SLisandro Dalcin 1289371c9d4SSatish Balay GmshCellEntry(1, SEG, 1, 1), GmshCellEntry(8, SEG, 1, 2), GmshCellEntry(26, SEG, 1, 3), 1299371c9d4SSatish Balay GmshCellEntry(27, SEG, 1, 4), GmshCellEntry(28, SEG, 1, 5), GmshCellEntry(62, SEG, 1, 6), 1309371c9d4SSatish Balay GmshCellEntry(63, SEG, 1, 7), GmshCellEntry(64, SEG, 1, 8), GmshCellEntry(65, SEG, 1, 9), 131066ea43fSLisandro Dalcin GmshCellEntry(66, SEG, 1, 10), 1320598e1a2SLisandro Dalcin 1339371c9d4SSatish Balay GmshCellEntry(2, TRI, 2, 1), GmshCellEntry(9, TRI, 2, 2), GmshCellEntry(21, TRI, 2, 3), 1349371c9d4SSatish Balay GmshCellEntry(23, TRI, 2, 4), GmshCellEntry(25, TRI, 2, 5), GmshCellEntry(42, TRI, 2, 6), 1359371c9d4SSatish Balay GmshCellEntry(43, TRI, 2, 7), GmshCellEntry(44, TRI, 2, 8), GmshCellEntry(45, TRI, 2, 9), 136066ea43fSLisandro Dalcin GmshCellEntry(46, TRI, 2, 10), 1370598e1a2SLisandro Dalcin 1389371c9d4SSatish Balay GmshCellEntry(3, QUA, 2, 1), GmshCellEntry(10, QUA, 2, 2), {16, GMSH_QUA, 2, 2, 4, 8, GmshLexOrder_QUA_2_Serendipity}, 1399371c9d4SSatish Balay GmshCellEntry(36, QUA, 2, 3), GmshCellEntry(37, QUA, 2, 4), GmshCellEntry(38, QUA, 2, 5), 1409371c9d4SSatish Balay GmshCellEntry(47, QUA, 2, 6), GmshCellEntry(48, QUA, 2, 7), GmshCellEntry(49, QUA, 2, 8), 1419371c9d4SSatish Balay GmshCellEntry(50, QUA, 2, 9), GmshCellEntry(51, QUA, 2, 10), 1420598e1a2SLisandro Dalcin 1439371c9d4SSatish Balay GmshCellEntry(4, TET, 3, 1), GmshCellEntry(11, TET, 3, 2), GmshCellEntry(29, TET, 3, 3), 1449371c9d4SSatish Balay GmshCellEntry(30, TET, 3, 4), GmshCellEntry(31, TET, 3, 5), GmshCellEntry(71, TET, 3, 6), 1459371c9d4SSatish Balay GmshCellEntry(72, TET, 3, 7), GmshCellEntry(73, TET, 3, 8), GmshCellEntry(74, TET, 3, 9), 146066ea43fSLisandro Dalcin GmshCellEntry(75, TET, 3, 10), 1470598e1a2SLisandro Dalcin 1489371c9d4SSatish Balay GmshCellEntry(5, HEX, 3, 1), GmshCellEntry(12, HEX, 3, 2), {17, GMSH_HEX, 3, 2, 8, 20, GmshLexOrder_HEX_2_Serendipity}, 1499371c9d4SSatish Balay GmshCellEntry(92, HEX, 3, 3), GmshCellEntry(93, HEX, 3, 4), GmshCellEntry(94, HEX, 3, 5), 1509371c9d4SSatish Balay GmshCellEntry(95, HEX, 3, 6), GmshCellEntry(96, HEX, 3, 7), GmshCellEntry(97, HEX, 3, 8), 1519371c9d4SSatish Balay GmshCellEntry(98, HEX, 3, 9), GmshCellEntry(-1, HEX, 3, 10), 1520598e1a2SLisandro Dalcin 1539371c9d4SSatish Balay GmshCellEntry(6, PRI, 3, 1), GmshCellEntry(13, PRI, 3, 2), GmshCellEntry(90, PRI, 3, 3), 1549371c9d4SSatish Balay GmshCellEntry(91, PRI, 3, 4), GmshCellEntry(106, PRI, 3, 5), GmshCellEntry(107, PRI, 3, 6), 1559371c9d4SSatish Balay GmshCellEntry(108, PRI, 3, 7), GmshCellEntry(109, PRI, 3, 8), GmshCellEntry(110, PRI, 3, 9), 156066ea43fSLisandro Dalcin GmshCellEntry(-1, PRI, 3, 10), 1570598e1a2SLisandro Dalcin 1589371c9d4SSatish Balay GmshCellEntry(7, PYR, 3, 1), GmshCellEntry(14, PYR, 3, 2), GmshCellEntry(118, PYR, 3, 3), 1599371c9d4SSatish Balay GmshCellEntry(119, PYR, 3, 4), GmshCellEntry(120, PYR, 3, 5), GmshCellEntry(121, PYR, 3, 6), 1609371c9d4SSatish Balay GmshCellEntry(122, PYR, 3, 7), GmshCellEntry(123, PYR, 3, 8), GmshCellEntry(124, PYR, 3, 9), 161066ea43fSLisandro Dalcin GmshCellEntry(-1, PYR, 3, 10) 1620598e1a2SLisandro Dalcin 1630598e1a2SLisandro Dalcin #if 0 164066ea43fSLisandro Dalcin {20, GMSH_TRI, 2, 3, 3, 9, NULL}, 165066ea43fSLisandro Dalcin {18, GMSH_PRI, 3, 2, 6, 15, NULL}, 166066ea43fSLisandro Dalcin {19, GMSH_PYR, 3, 2, 5, 13, NULL}, 1670598e1a2SLisandro Dalcin #endif 1680598e1a2SLisandro Dalcin }; 1690598e1a2SLisandro Dalcin 1700598e1a2SLisandro Dalcin static GmshCellInfo GmshCellMap[150]; 1710598e1a2SLisandro Dalcin 172d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshCellInfoSetUp(void) 173d71ae5a4SJacob Faibussowitsch { 1740598e1a2SLisandro Dalcin size_t i, n; 1750598e1a2SLisandro Dalcin static PetscBool called = PETSC_FALSE; 1760598e1a2SLisandro Dalcin 1773ba16761SJacob Faibussowitsch if (called) return PETSC_SUCCESS; 1780598e1a2SLisandro Dalcin PetscFunctionBegin; 1790598e1a2SLisandro Dalcin called = PETSC_TRUE; 180dd39110bSPierre Jolivet n = PETSC_STATIC_ARRAY_LENGTH(GmshCellMap); 1810598e1a2SLisandro Dalcin for (i = 0; i < n; ++i) { 1820598e1a2SLisandro Dalcin GmshCellMap[i].cellType = -1; 183066ea43fSLisandro Dalcin GmshCellMap[i].polytope = -1; 1840598e1a2SLisandro Dalcin } 185dd39110bSPierre Jolivet n = PETSC_STATIC_ARRAY_LENGTH(GmshCellTable); 186066ea43fSLisandro Dalcin for (i = 0; i < n; ++i) { 187066ea43fSLisandro Dalcin if (GmshCellTable[i].cellType <= 0) continue; 188066ea43fSLisandro Dalcin GmshCellMap[GmshCellTable[i].cellType] = GmshCellTable[i]; 189066ea43fSLisandro Dalcin } 1903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1910598e1a2SLisandro Dalcin } 1920598e1a2SLisandro Dalcin 1939371c9d4SSatish Balay #define GmshCellTypeCheck(ct) \ 1949371c9d4SSatish Balay PetscMacroReturnStandard(const int _ct_ = (int)ct; PetscCheck(_ct_ >= 0 && _ct_ < (int)PETSC_STATIC_ARRAY_LENGTH(GmshCellMap), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid Gmsh element type %d", _ct_); PetscCheck(GmshCellMap[_ct_].cellType == _ct_, PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported Gmsh element type %d", _ct_); \ 1959371c9d4SSatish Balay PetscCheck(GmshCellMap[_ct_].polytope != -1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported Gmsh element type %d", _ct_);) 1960598e1a2SLisandro Dalcin 1970598e1a2SLisandro Dalcin typedef struct { 198698a79b9SLisandro Dalcin PetscViewer viewer; 199698a79b9SLisandro Dalcin int fileFormat; 200698a79b9SLisandro Dalcin int dataSize; 201698a79b9SLisandro Dalcin PetscBool binary; 202698a79b9SLisandro Dalcin PetscBool byteSwap; 203698a79b9SLisandro Dalcin size_t wlen; 204698a79b9SLisandro Dalcin void *wbuf; 205698a79b9SLisandro Dalcin size_t slen; 206698a79b9SLisandro Dalcin void *sbuf; 2070598e1a2SLisandro Dalcin PetscInt *nbuf; 2080598e1a2SLisandro Dalcin PetscInt nodeStart; 2090598e1a2SLisandro Dalcin PetscInt nodeEnd; 21033a088b6SMatthew G. Knepley PetscInt *nodeMap; 211698a79b9SLisandro Dalcin } GmshFile; 212de78e4feSLisandro Dalcin 213d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshBufferGet(GmshFile *gmsh, size_t count, size_t eltsize, void *buf) 214d71ae5a4SJacob Faibussowitsch { 215de78e4feSLisandro Dalcin size_t size = count * eltsize; 21611c56cb0SLisandro Dalcin 21711c56cb0SLisandro Dalcin PetscFunctionBegin; 218698a79b9SLisandro Dalcin if (gmsh->wlen < size) { 2199566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->wbuf)); 2209566063dSJacob Faibussowitsch PetscCall(PetscMalloc(size, &gmsh->wbuf)); 221698a79b9SLisandro Dalcin gmsh->wlen = size; 222de78e4feSLisandro Dalcin } 223698a79b9SLisandro Dalcin *(void **)buf = size ? gmsh->wbuf : NULL; 2243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 225de78e4feSLisandro Dalcin } 226de78e4feSLisandro Dalcin 227d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshBufferSizeGet(GmshFile *gmsh, size_t count, void *buf) 228d71ae5a4SJacob Faibussowitsch { 229698a79b9SLisandro Dalcin size_t dataSize = (size_t)gmsh->dataSize; 230698a79b9SLisandro Dalcin size_t size = count * dataSize; 231698a79b9SLisandro Dalcin 232698a79b9SLisandro Dalcin PetscFunctionBegin; 233698a79b9SLisandro Dalcin if (gmsh->slen < size) { 2349566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->sbuf)); 2359566063dSJacob Faibussowitsch PetscCall(PetscMalloc(size, &gmsh->sbuf)); 236698a79b9SLisandro Dalcin gmsh->slen = size; 237698a79b9SLisandro Dalcin } 238698a79b9SLisandro Dalcin *(void **)buf = size ? gmsh->sbuf : NULL; 2393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 240698a79b9SLisandro Dalcin } 241698a79b9SLisandro Dalcin 242d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshRead(GmshFile *gmsh, void *buf, PetscInt count, PetscDataType dtype) 243d71ae5a4SJacob Faibussowitsch { 244de78e4feSLisandro Dalcin PetscFunctionBegin; 2459566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(gmsh->viewer, buf, count, NULL, dtype)); 2469566063dSJacob Faibussowitsch if (gmsh->byteSwap) PetscCall(PetscByteSwap(buf, dtype, count)); 2473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 248698a79b9SLisandro Dalcin } 249698a79b9SLisandro Dalcin 250d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadString(GmshFile *gmsh, char *buf, PetscInt count) 251d71ae5a4SJacob Faibussowitsch { 252698a79b9SLisandro Dalcin PetscFunctionBegin; 2539566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(gmsh->viewer, buf, count, NULL, PETSC_STRING)); 2543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 255698a79b9SLisandro Dalcin } 256698a79b9SLisandro Dalcin 257d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshMatch(PETSC_UNUSED GmshFile *gmsh, const char Section[], char line[PETSC_MAX_PATH_LEN], PetscBool *match) 258d71ae5a4SJacob Faibussowitsch { 259d6689ca9SLisandro Dalcin PetscFunctionBegin; 2609566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(line, Section, match)); 2613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 262d6689ca9SLisandro Dalcin } 263d6689ca9SLisandro Dalcin 264d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshExpect(GmshFile *gmsh, const char Section[], char line[PETSC_MAX_PATH_LEN]) 265d71ae5a4SJacob Faibussowitsch { 266d6689ca9SLisandro Dalcin PetscBool match; 267d6689ca9SLisandro Dalcin 268d6689ca9SLisandro Dalcin PetscFunctionBegin; 2699566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, Section, line, &match)); 27028b400f6SJacob Faibussowitsch PetscCheck(match, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file, expecting %s", Section); 2713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 272d6689ca9SLisandro Dalcin } 273d6689ca9SLisandro Dalcin 274d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadSection(GmshFile *gmsh, char line[PETSC_MAX_PATH_LEN]) 275d71ae5a4SJacob Faibussowitsch { 276d6689ca9SLisandro Dalcin PetscBool match; 277d6689ca9SLisandro Dalcin 278d6689ca9SLisandro Dalcin PetscFunctionBegin; 279d6689ca9SLisandro Dalcin while (PETSC_TRUE) { 2809566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 1)); 2819566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, "$Comments", line, &match)); 282d6689ca9SLisandro Dalcin if (!match) break; 283d6689ca9SLisandro Dalcin while (PETSC_TRUE) { 2849566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 1)); 2859566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, "$EndComments", line, &match)); 286d6689ca9SLisandro Dalcin if (match) break; 287d6689ca9SLisandro Dalcin } 288d6689ca9SLisandro Dalcin } 2893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 290d6689ca9SLisandro Dalcin } 291d6689ca9SLisandro Dalcin 292d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEndSection(GmshFile *gmsh, const char EndSection[], char line[PETSC_MAX_PATH_LEN]) 293d71ae5a4SJacob Faibussowitsch { 294d6689ca9SLisandro Dalcin PetscFunctionBegin; 2959566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 1)); 2969566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, EndSection, line)); 2973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 298d6689ca9SLisandro Dalcin } 299d6689ca9SLisandro Dalcin 300d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadSize(GmshFile *gmsh, PetscInt *buf, PetscInt count) 301d71ae5a4SJacob Faibussowitsch { 302698a79b9SLisandro Dalcin PetscInt i; 303698a79b9SLisandro Dalcin size_t dataSize = (size_t)gmsh->dataSize; 304698a79b9SLisandro Dalcin 305698a79b9SLisandro Dalcin PetscFunctionBegin; 306698a79b9SLisandro Dalcin if (dataSize == sizeof(PetscInt)) { 3079566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, buf, count, PETSC_INT)); 308698a79b9SLisandro Dalcin } else if (dataSize == sizeof(int)) { 309698a79b9SLisandro Dalcin int *ibuf = NULL; 3109566063dSJacob Faibussowitsch PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf)); 3119566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, ibuf, count, PETSC_ENUM)); 312698a79b9SLisandro Dalcin for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i]; 313698a79b9SLisandro Dalcin } else if (dataSize == sizeof(long)) { 314698a79b9SLisandro Dalcin long *ibuf = NULL; 3159566063dSJacob Faibussowitsch PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf)); 3169566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, ibuf, count, PETSC_LONG)); 317698a79b9SLisandro Dalcin for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i]; 318698a79b9SLisandro Dalcin } else if (dataSize == sizeof(PetscInt64)) { 319698a79b9SLisandro Dalcin PetscInt64 *ibuf = NULL; 3209566063dSJacob Faibussowitsch PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf)); 3219566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, ibuf, count, PETSC_INT64)); 322698a79b9SLisandro Dalcin for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i]; 323698a79b9SLisandro Dalcin } 3243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 325698a79b9SLisandro Dalcin } 326698a79b9SLisandro Dalcin 327d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadInt(GmshFile *gmsh, int *buf, PetscInt count) 328d71ae5a4SJacob Faibussowitsch { 329698a79b9SLisandro Dalcin PetscFunctionBegin; 3309566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, buf, count, PETSC_ENUM)); 3313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 332698a79b9SLisandro Dalcin } 333698a79b9SLisandro Dalcin 334d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadDouble(GmshFile *gmsh, double *buf, PetscInt count) 335d71ae5a4SJacob Faibussowitsch { 336698a79b9SLisandro Dalcin PetscFunctionBegin; 3379566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, buf, count, PETSC_DOUBLE)); 3383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 339de78e4feSLisandro Dalcin } 340de78e4feSLisandro Dalcin 3419c0edc59SMatthew G. Knepley #define GMSH_MAX_TAGS 16 3427d5b9244SMatthew G. Knepley 343de78e4feSLisandro Dalcin typedef struct { 3440598e1a2SLisandro Dalcin PetscInt id; /* Entity ID */ 3450598e1a2SLisandro Dalcin PetscInt dim; /* Dimension */ 346de78e4feSLisandro Dalcin double bbox[6]; /* Bounding box */ 347de78e4feSLisandro Dalcin PetscInt numTags; /* Size of tag array */ 3487d5b9244SMatthew G. Knepley int tags[GMSH_MAX_TAGS]; /* Tag array */ 349de78e4feSLisandro Dalcin } GmshEntity; 350de78e4feSLisandro Dalcin 351de78e4feSLisandro Dalcin typedef struct { 352730356f6SLisandro Dalcin GmshEntity *entity[4]; 353730356f6SLisandro Dalcin PetscHMapI entityMap[4]; 354730356f6SLisandro Dalcin } GmshEntities; 355730356f6SLisandro Dalcin 356d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshEntitiesCreate(PetscInt count[4], GmshEntities **entities) 357d71ae5a4SJacob Faibussowitsch { 358730356f6SLisandro Dalcin PetscInt dim; 359730356f6SLisandro Dalcin 360730356f6SLisandro Dalcin PetscFunctionBegin; 3619566063dSJacob Faibussowitsch PetscCall(PetscNew(entities)); 362730356f6SLisandro Dalcin for (dim = 0; dim < 4; ++dim) { 3639566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(count[dim], &(*entities)->entity[dim])); 3649566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&(*entities)->entityMap[dim])); 365730356f6SLisandro Dalcin } 3663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 367730356f6SLisandro Dalcin } 368730356f6SLisandro Dalcin 369d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshEntitiesDestroy(GmshEntities **entities) 370d71ae5a4SJacob Faibussowitsch { 3710598e1a2SLisandro Dalcin PetscInt dim; 3720598e1a2SLisandro Dalcin 3730598e1a2SLisandro Dalcin PetscFunctionBegin; 3743ba16761SJacob Faibussowitsch if (!*entities) PetscFunctionReturn(PETSC_SUCCESS); 3750598e1a2SLisandro Dalcin for (dim = 0; dim < 4; ++dim) { 3769566063dSJacob Faibussowitsch PetscCall(PetscFree((*entities)->entity[dim])); 3779566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&(*entities)->entityMap[dim])); 3780598e1a2SLisandro Dalcin } 3799566063dSJacob Faibussowitsch PetscCall(PetscFree((*entities))); 3803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3810598e1a2SLisandro Dalcin } 3820598e1a2SLisandro Dalcin 383d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshEntitiesAdd(GmshEntities *entities, PetscInt index, PetscInt dim, PetscInt eid, GmshEntity **entity) 384d71ae5a4SJacob Faibussowitsch { 385730356f6SLisandro Dalcin PetscFunctionBegin; 3869566063dSJacob Faibussowitsch PetscCall(PetscHMapISet(entities->entityMap[dim], eid, index)); 387730356f6SLisandro Dalcin entities->entity[dim][index].dim = dim; 388730356f6SLisandro Dalcin entities->entity[dim][index].id = eid; 389730356f6SLisandro Dalcin if (entity) *entity = &entities->entity[dim][index]; 3903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 391730356f6SLisandro Dalcin } 392730356f6SLisandro Dalcin 393d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshEntitiesGet(GmshEntities *entities, PetscInt dim, PetscInt eid, GmshEntity **entity) 394d71ae5a4SJacob Faibussowitsch { 395730356f6SLisandro Dalcin PetscInt index; 396730356f6SLisandro Dalcin 397730356f6SLisandro Dalcin PetscFunctionBegin; 3989566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(entities->entityMap[dim], eid, &index)); 399730356f6SLisandro Dalcin *entity = &entities->entity[dim][index]; 4003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 401730356f6SLisandro Dalcin } 402730356f6SLisandro Dalcin 4030598e1a2SLisandro Dalcin typedef struct { 4040598e1a2SLisandro Dalcin PetscInt *id; /* Node IDs */ 4050598e1a2SLisandro Dalcin double *xyz; /* Coordinates */ 40681a1af93SMatthew G. Knepley PetscInt *tag; /* Physical tag */ 4070598e1a2SLisandro Dalcin } GmshNodes; 4080598e1a2SLisandro Dalcin 409d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshNodesCreate(PetscInt count, GmshNodes **nodes) 410d71ae5a4SJacob Faibussowitsch { 411730356f6SLisandro Dalcin PetscFunctionBegin; 4129566063dSJacob Faibussowitsch PetscCall(PetscNew(nodes)); 4139566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(count * 1, &(*nodes)->id)); 4149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(count * 3, &(*nodes)->xyz)); 4157d5b9244SMatthew G. Knepley PetscCall(PetscMalloc1(count * GMSH_MAX_TAGS, &(*nodes)->tag)); 4163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 417730356f6SLisandro Dalcin } 4180598e1a2SLisandro Dalcin 419d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshNodesDestroy(GmshNodes **nodes) 420d71ae5a4SJacob Faibussowitsch { 4210598e1a2SLisandro Dalcin PetscFunctionBegin; 4223ba16761SJacob Faibussowitsch if (!*nodes) PetscFunctionReturn(PETSC_SUCCESS); 4239566063dSJacob Faibussowitsch PetscCall(PetscFree((*nodes)->id)); 4249566063dSJacob Faibussowitsch PetscCall(PetscFree((*nodes)->xyz)); 4259566063dSJacob Faibussowitsch PetscCall(PetscFree((*nodes)->tag)); 4269566063dSJacob Faibussowitsch PetscCall(PetscFree((*nodes))); 4273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 428730356f6SLisandro Dalcin } 429730356f6SLisandro Dalcin 430730356f6SLisandro Dalcin typedef struct { 4310598e1a2SLisandro Dalcin PetscInt id; /* Element ID */ 4320598e1a2SLisandro Dalcin PetscInt dim; /* Dimension */ 433de78e4feSLisandro Dalcin PetscInt cellType; /* Cell type */ 4340598e1a2SLisandro Dalcin PetscInt numVerts; /* Size of vertex array */ 435de78e4feSLisandro Dalcin PetscInt numNodes; /* Size of node array */ 4360598e1a2SLisandro Dalcin PetscInt *nodes; /* Vertex/Node array */ 43781a1af93SMatthew G. Knepley PetscInt numTags; /* Size of physical tag array */ 4387d5b9244SMatthew G. Knepley int tags[GMSH_MAX_TAGS]; /* Physical tag array */ 439de78e4feSLisandro Dalcin } GmshElement; 440de78e4feSLisandro Dalcin 441d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshElementsCreate(PetscInt count, GmshElement **elements) 442d71ae5a4SJacob Faibussowitsch { 4430598e1a2SLisandro Dalcin PetscFunctionBegin; 4449566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(count, elements)); 4453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4460598e1a2SLisandro Dalcin } 4470598e1a2SLisandro Dalcin 448d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshElementsDestroy(GmshElement **elements) 449d71ae5a4SJacob Faibussowitsch { 4500598e1a2SLisandro Dalcin PetscFunctionBegin; 4513ba16761SJacob Faibussowitsch if (!*elements) PetscFunctionReturn(PETSC_SUCCESS); 4529566063dSJacob Faibussowitsch PetscCall(PetscFree(*elements)); 4533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4540598e1a2SLisandro Dalcin } 4550598e1a2SLisandro Dalcin 4560598e1a2SLisandro Dalcin typedef struct { 4570598e1a2SLisandro Dalcin PetscInt dim; 458066ea43fSLisandro Dalcin PetscInt order; 4590598e1a2SLisandro Dalcin GmshEntities *entities; 4600598e1a2SLisandro Dalcin PetscInt numNodes; 4610598e1a2SLisandro Dalcin GmshNodes *nodelist; 4620598e1a2SLisandro Dalcin PetscInt numElems; 4630598e1a2SLisandro Dalcin GmshElement *elements; 4640598e1a2SLisandro Dalcin PetscInt numVerts; 4650598e1a2SLisandro Dalcin PetscInt numCells; 4660598e1a2SLisandro Dalcin PetscInt *periodMap; 4670598e1a2SLisandro Dalcin PetscInt *vertexMap; 4680598e1a2SLisandro Dalcin PetscSegBuffer segbuf; 469a45dabc8SMatthew G. Knepley PetscInt numRegions; 47090d778b8SLisandro Dalcin PetscInt *regionDims; 471a45dabc8SMatthew G. Knepley PetscInt *regionTags; 472a45dabc8SMatthew G. Knepley char **regionNames; 4730598e1a2SLisandro Dalcin } GmshMesh; 4740598e1a2SLisandro Dalcin 475d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshMeshCreate(GmshMesh **mesh) 476d71ae5a4SJacob Faibussowitsch { 4770598e1a2SLisandro Dalcin PetscFunctionBegin; 4789566063dSJacob Faibussowitsch PetscCall(PetscNew(mesh)); 4799566063dSJacob Faibussowitsch PetscCall(PetscSegBufferCreate(sizeof(PetscInt), 0, &(*mesh)->segbuf)); 4803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4810598e1a2SLisandro Dalcin } 4820598e1a2SLisandro Dalcin 483d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshMeshDestroy(GmshMesh **mesh) 484d71ae5a4SJacob Faibussowitsch { 485a45dabc8SMatthew G. Knepley PetscInt r; 4860598e1a2SLisandro Dalcin 4870598e1a2SLisandro Dalcin PetscFunctionBegin; 4883ba16761SJacob Faibussowitsch if (!*mesh) PetscFunctionReturn(PETSC_SUCCESS); 4899566063dSJacob Faibussowitsch PetscCall(GmshEntitiesDestroy(&(*mesh)->entities)); 4909566063dSJacob Faibussowitsch PetscCall(GmshNodesDestroy(&(*mesh)->nodelist)); 4919566063dSJacob Faibussowitsch PetscCall(GmshElementsDestroy(&(*mesh)->elements)); 4929566063dSJacob Faibussowitsch PetscCall(PetscFree((*mesh)->periodMap)); 4939566063dSJacob Faibussowitsch PetscCall(PetscFree((*mesh)->vertexMap)); 4949566063dSJacob Faibussowitsch PetscCall(PetscSegBufferDestroy(&(*mesh)->segbuf)); 4959566063dSJacob Faibussowitsch for (r = 0; r < (*mesh)->numRegions; ++r) PetscCall(PetscFree((*mesh)->regionNames[r])); 49690d778b8SLisandro Dalcin PetscCall(PetscFree3((*mesh)->regionDims, (*mesh)->regionTags, (*mesh)->regionNames)); 4979566063dSJacob Faibussowitsch PetscCall(PetscFree((*mesh))); 4983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4990598e1a2SLisandro Dalcin } 5000598e1a2SLisandro Dalcin 501d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes_v22(GmshFile *gmsh, GmshMesh *mesh) 502d71ae5a4SJacob Faibussowitsch { 503698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 504698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 505de78e4feSLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 5067d5b9244SMatthew G. Knepley int n, t, num, nid, snum; 5070598e1a2SLisandro Dalcin GmshNodes *nodes; 508de78e4feSLisandro Dalcin 509de78e4feSLisandro Dalcin PetscFunctionBegin; 5109566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 511698a79b9SLisandro Dalcin snum = sscanf(line, "%d", &num); 51208401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 5139566063dSJacob Faibussowitsch PetscCall(GmshNodesCreate(num, &nodes)); 5140598e1a2SLisandro Dalcin mesh->numNodes = num; 5150598e1a2SLisandro Dalcin mesh->nodelist = nodes; 5160598e1a2SLisandro Dalcin for (n = 0; n < num; ++n) { 5170598e1a2SLisandro Dalcin double *xyz = nodes->xyz + n * 3; 5189566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM)); 5199566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE)); 5209566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nid, PETSC_ENUM, 1)); 5219566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(xyz, PETSC_DOUBLE, 3)); 5220598e1a2SLisandro Dalcin nodes->id[n] = nid; 5237d5b9244SMatthew G. Knepley for (t = 0; t < GMSH_MAX_TAGS; ++t) nodes->tag[n * GMSH_MAX_TAGS + t] = -1; 52411c56cb0SLisandro Dalcin } 5253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 52611c56cb0SLisandro Dalcin } 52711c56cb0SLisandro Dalcin 528de78e4feSLisandro Dalcin /* Gmsh elements can be of any dimension/co-dimension, so we need to traverse the 529de78e4feSLisandro Dalcin file contents multiple times to figure out the true number of cells and facets 530de78e4feSLisandro Dalcin in the given mesh. To make this more efficient we read the file contents only 531de78e4feSLisandro Dalcin once and store them in memory, while determining the true number of cells. */ 532d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements_v22(GmshFile *gmsh, GmshMesh *mesh) 533d71ae5a4SJacob Faibussowitsch { 534698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 535698a79b9SLisandro Dalcin PetscBool binary = gmsh->binary; 536698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 537de78e4feSLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 5380598e1a2SLisandro Dalcin int i, c, p, num, ibuf[1 + 4 + 1000], snum; 5390598e1a2SLisandro Dalcin int cellType, numElem, numVerts, numNodes, numTags; 540df032b82SMatthew G. Knepley GmshElement *elements; 5410598e1a2SLisandro Dalcin PetscInt *nodeMap = gmsh->nodeMap; 542df032b82SMatthew G. Knepley 543df032b82SMatthew G. Knepley PetscFunctionBegin; 5449566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 545698a79b9SLisandro Dalcin snum = sscanf(line, "%d", &num); 54608401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 5479566063dSJacob Faibussowitsch PetscCall(GmshElementsCreate(num, &elements)); 5480598e1a2SLisandro Dalcin mesh->numElems = num; 5490598e1a2SLisandro Dalcin mesh->elements = elements; 550698a79b9SLisandro Dalcin for (c = 0; c < num;) { 5519566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM)); 5529566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, 3)); 5530598e1a2SLisandro Dalcin 5540598e1a2SLisandro Dalcin cellType = binary ? ibuf[0] : ibuf[1]; 5550598e1a2SLisandro Dalcin numElem = binary ? ibuf[1] : 1; 556df032b82SMatthew G. Knepley numTags = ibuf[2]; 5570598e1a2SLisandro Dalcin 5589566063dSJacob Faibussowitsch PetscCall(GmshCellTypeCheck(cellType)); 5590598e1a2SLisandro Dalcin numVerts = GmshCellMap[cellType].numVerts; 5600598e1a2SLisandro Dalcin numNodes = GmshCellMap[cellType].numNodes; 5610598e1a2SLisandro Dalcin 562df032b82SMatthew G. Knepley for (i = 0; i < numElem; ++i, ++c) { 5630598e1a2SLisandro Dalcin GmshElement *element = elements + c; 5640598e1a2SLisandro Dalcin const int off = binary ? 0 : 1, nint = 1 + numTags + numNodes - off; 5650598e1a2SLisandro Dalcin const int *id = ibuf, *nodes = ibuf + 1 + numTags, *tags = ibuf + 1; 5669566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf + off, nint, NULL, PETSC_ENUM)); 5679566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf + off, PETSC_ENUM, nint)); 5680598e1a2SLisandro Dalcin element->id = id[0]; 5690598e1a2SLisandro Dalcin element->dim = GmshCellMap[cellType].dim; 5700598e1a2SLisandro Dalcin element->cellType = cellType; 5710598e1a2SLisandro Dalcin element->numVerts = numVerts; 5720598e1a2SLisandro Dalcin element->numNodes = numNodes; 5737d5b9244SMatthew G. Knepley element->numTags = PetscMin(numTags, GMSH_MAX_TAGS); 5749566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes)); 5750598e1a2SLisandro Dalcin for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]]; 5760598e1a2SLisandro Dalcin for (p = 0; p < element->numTags; p++) element->tags[p] = tags[p]; 577df032b82SMatthew G. Knepley } 578df032b82SMatthew G. Knepley } 5793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 580df032b82SMatthew G. Knepley } 5817d282ae0SMichael Lange 582de78e4feSLisandro Dalcin /* 583de78e4feSLisandro Dalcin $Entities 584de78e4feSLisandro Dalcin numPoints(unsigned long) numCurves(unsigned long) 585de78e4feSLisandro Dalcin numSurfaces(unsigned long) numVolumes(unsigned long) 586de78e4feSLisandro Dalcin // points 587de78e4feSLisandro Dalcin tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 588de78e4feSLisandro Dalcin boxMaxX(double) boxMaxY(double) boxMaxZ(double) 589de78e4feSLisandro Dalcin numPhysicals(unsigned long) phyisicalTag[...](int) 590de78e4feSLisandro Dalcin ... 591de78e4feSLisandro Dalcin // curves 592de78e4feSLisandro Dalcin tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 593de78e4feSLisandro Dalcin boxMaxX(double) boxMaxY(double) boxMaxZ(double) 594de78e4feSLisandro Dalcin numPhysicals(unsigned long) physicalTag[...](int) 595de78e4feSLisandro Dalcin numBREPVert(unsigned long) tagBREPVert[...](int) 596de78e4feSLisandro Dalcin ... 597de78e4feSLisandro Dalcin // surfaces 598de78e4feSLisandro Dalcin tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 599de78e4feSLisandro Dalcin boxMaxX(double) boxMaxY(double) boxMaxZ(double) 600de78e4feSLisandro Dalcin numPhysicals(unsigned long) physicalTag[...](int) 601de78e4feSLisandro Dalcin numBREPCurve(unsigned long) tagBREPCurve[...](int) 602de78e4feSLisandro Dalcin ... 603de78e4feSLisandro Dalcin // volumes 604de78e4feSLisandro Dalcin tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 605de78e4feSLisandro Dalcin boxMaxX(double) boxMaxY(double) boxMaxZ(double) 606de78e4feSLisandro Dalcin numPhysicals(unsigned long) physicalTag[...](int) 607de78e4feSLisandro Dalcin numBREPSurfaces(unsigned long) tagBREPSurfaces[...](int) 608de78e4feSLisandro Dalcin ... 609de78e4feSLisandro Dalcin $EndEntities 610de78e4feSLisandro Dalcin */ 611d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEntities_v40(GmshFile *gmsh, GmshMesh *mesh) 612d71ae5a4SJacob Faibussowitsch { 613698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 614698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 615698a79b9SLisandro Dalcin long index, num, lbuf[4]; 616730356f6SLisandro Dalcin int dim, eid, numTags, *ibuf, t; 617698a79b9SLisandro Dalcin PetscInt count[4], i; 618a5ba3d71SLisandro Dalcin GmshEntity *entity = NULL; 619de78e4feSLisandro Dalcin 620de78e4feSLisandro Dalcin PetscFunctionBegin; 6219566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, lbuf, 4, NULL, PETSC_LONG)); 6229566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(lbuf, PETSC_LONG, 4)); 623698a79b9SLisandro Dalcin for (i = 0; i < 4; ++i) count[i] = lbuf[i]; 6249566063dSJacob Faibussowitsch PetscCall(GmshEntitiesCreate(count, &mesh->entities)); 625de78e4feSLisandro Dalcin for (dim = 0; dim < 4; ++dim) { 626730356f6SLisandro Dalcin for (index = 0; index < count[dim]; ++index) { 6279566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &eid, 1, NULL, PETSC_ENUM)); 6289566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&eid, PETSC_ENUM, 1)); 6299566063dSJacob Faibussowitsch PetscCall(GmshEntitiesAdd(mesh->entities, (PetscInt)index, dim, eid, &entity)); 6309566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, entity->bbox, 6, NULL, PETSC_DOUBLE)); 6319566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(entity->bbox, PETSC_DOUBLE, 6)); 6329566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &num, 1, NULL, PETSC_LONG)); 6339566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&num, PETSC_LONG, 1)); 6349566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, num, sizeof(int), &ibuf)); 6359566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, num, NULL, PETSC_ENUM)); 6369566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, num)); 6377d5b9244SMatthew G. Knepley entity->numTags = numTags = (int)PetscMin(num, GMSH_MAX_TAGS); 638de78e4feSLisandro Dalcin for (t = 0; t < numTags; ++t) entity->tags[t] = ibuf[t]; 639de78e4feSLisandro Dalcin if (dim == 0) continue; 6409566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &num, 1, NULL, PETSC_LONG)); 6419566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&num, PETSC_LONG, 1)); 6429566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, num, sizeof(int), &ibuf)); 6439566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, num, NULL, PETSC_ENUM)); 6449566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, num)); 645de78e4feSLisandro Dalcin } 646de78e4feSLisandro Dalcin } 6473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 648de78e4feSLisandro Dalcin } 649de78e4feSLisandro Dalcin 650de78e4feSLisandro Dalcin /* 651de78e4feSLisandro Dalcin $Nodes 652de78e4feSLisandro Dalcin numEntityBlocks(unsigned long) numNodes(unsigned long) 653de78e4feSLisandro Dalcin tagEntity(int) dimEntity(int) typeNode(int) numNodes(unsigned long) 654de78e4feSLisandro Dalcin tag(int) x(double) y(double) z(double) 655de78e4feSLisandro Dalcin ... 656de78e4feSLisandro Dalcin ... 657de78e4feSLisandro Dalcin $EndNodes 658de78e4feSLisandro Dalcin */ 659d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes_v40(GmshFile *gmsh, GmshMesh *mesh) 660d71ae5a4SJacob Faibussowitsch { 661698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 662698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 6637d5b9244SMatthew G. Knepley long block, node, n, t, numEntityBlocks, numTotalNodes, numNodes; 664de78e4feSLisandro Dalcin int info[3], nid; 6650598e1a2SLisandro Dalcin GmshNodes *nodes; 666de78e4feSLisandro Dalcin 667de78e4feSLisandro Dalcin PetscFunctionBegin; 6689566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numEntityBlocks, 1, NULL, PETSC_LONG)); 6699566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numEntityBlocks, PETSC_LONG, 1)); 6709566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numTotalNodes, 1, NULL, PETSC_LONG)); 6719566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numTotalNodes, PETSC_LONG, 1)); 6729566063dSJacob Faibussowitsch PetscCall(GmshNodesCreate(numTotalNodes, &nodes)); 6730598e1a2SLisandro Dalcin mesh->numNodes = numTotalNodes; 6740598e1a2SLisandro Dalcin mesh->nodelist = nodes; 6750598e1a2SLisandro Dalcin for (n = 0, block = 0; block < numEntityBlocks; ++block) { 6769566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, info, 3, NULL, PETSC_ENUM)); 6779566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numNodes, 1, NULL, PETSC_LONG)); 6789566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numNodes, PETSC_LONG, 1)); 679698a79b9SLisandro Dalcin if (gmsh->binary) { 680277f51e8SBarry Smith size_t nbytes = sizeof(int) + 3 * sizeof(double); 681da81f932SPierre Jolivet char *cbuf = NULL; /* dummy value to prevent warning from compiler about possible uninitialized value */ 6829566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, numNodes, nbytes, &cbuf)); 6839566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, cbuf, numNodes * nbytes, NULL, PETSC_CHAR)); 6840598e1a2SLisandro Dalcin for (node = 0; node < numNodes; ++node, ++n) { 685de78e4feSLisandro Dalcin char *cnid = cbuf + node * nbytes, *cxyz = cnid + sizeof(int); 6860598e1a2SLisandro Dalcin double *xyz = nodes->xyz + n * 3; 6879566063dSJacob Faibussowitsch if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(cnid, PETSC_ENUM, 1)); 6889566063dSJacob Faibussowitsch if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(cxyz, PETSC_DOUBLE, 3)); 6899566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(&nid, cnid, sizeof(int))); 6909566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(xyz, cxyz, 3 * sizeof(double))); 6919566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nid, PETSC_ENUM, 1)); 6929566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(xyz, PETSC_DOUBLE, 3)); 6930598e1a2SLisandro Dalcin nodes->id[n] = nid; 6947d5b9244SMatthew G. Knepley for (t = 0; t < GMSH_MAX_TAGS; ++t) nodes->tag[n * GMSH_MAX_TAGS + t] = -1; 695de78e4feSLisandro Dalcin } 696de78e4feSLisandro Dalcin } else { 6970598e1a2SLisandro Dalcin for (node = 0; node < numNodes; ++node, ++n) { 6980598e1a2SLisandro Dalcin double *xyz = nodes->xyz + n * 3; 6999566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM)); 7009566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE)); 7019566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nid, PETSC_ENUM, 1)); 7029566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(xyz, PETSC_DOUBLE, 3)); 7030598e1a2SLisandro Dalcin nodes->id[n] = nid; 7047d5b9244SMatthew G. Knepley for (t = 0; t < GMSH_MAX_TAGS; ++t) nodes->tag[n * GMSH_MAX_TAGS + t] = -1; 705de78e4feSLisandro Dalcin } 706de78e4feSLisandro Dalcin } 707de78e4feSLisandro Dalcin } 7083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 709de78e4feSLisandro Dalcin } 710de78e4feSLisandro Dalcin 711de78e4feSLisandro Dalcin /* 712de78e4feSLisandro Dalcin $Elements 713de78e4feSLisandro Dalcin numEntityBlocks(unsigned long) numElements(unsigned long) 714de78e4feSLisandro Dalcin tagEntity(int) dimEntity(int) typeEle(int) numElements(unsigned long) 715de78e4feSLisandro Dalcin tag(int) numVert[...](int) 716de78e4feSLisandro Dalcin ... 717de78e4feSLisandro Dalcin ... 718de78e4feSLisandro Dalcin $EndElements 719de78e4feSLisandro Dalcin */ 720d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements_v40(GmshFile *gmsh, GmshMesh *mesh) 721d71ae5a4SJacob Faibussowitsch { 722698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 723698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 724de78e4feSLisandro Dalcin long c, block, numEntityBlocks, numTotalElements, elem, numElements; 725de78e4feSLisandro Dalcin int p, info[3], *ibuf = NULL; 7260598e1a2SLisandro Dalcin int eid, dim, cellType, numVerts, numNodes, numTags; 727a5ba3d71SLisandro Dalcin GmshEntity *entity = NULL; 728de78e4feSLisandro Dalcin GmshElement *elements; 7290598e1a2SLisandro Dalcin PetscInt *nodeMap = gmsh->nodeMap; 730de78e4feSLisandro Dalcin 731de78e4feSLisandro Dalcin PetscFunctionBegin; 7329566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numEntityBlocks, 1, NULL, PETSC_LONG)); 7339566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numEntityBlocks, PETSC_LONG, 1)); 7349566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numTotalElements, 1, NULL, PETSC_LONG)); 7359566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numTotalElements, PETSC_LONG, 1)); 7369566063dSJacob Faibussowitsch PetscCall(GmshElementsCreate(numTotalElements, &elements)); 7370598e1a2SLisandro Dalcin mesh->numElems = numTotalElements; 7380598e1a2SLisandro Dalcin mesh->elements = elements; 739de78e4feSLisandro Dalcin for (c = 0, block = 0; block < numEntityBlocks; ++block) { 7409566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, info, 3, NULL, PETSC_ENUM)); 7419566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(info, PETSC_ENUM, 3)); 7429371c9d4SSatish Balay eid = info[0]; 7439371c9d4SSatish Balay dim = info[1]; 7449371c9d4SSatish Balay cellType = info[2]; 7459566063dSJacob Faibussowitsch PetscCall(GmshEntitiesGet(mesh->entities, dim, eid, &entity)); 7469566063dSJacob Faibussowitsch PetscCall(GmshCellTypeCheck(cellType)); 7470598e1a2SLisandro Dalcin numVerts = GmshCellMap[cellType].numVerts; 7480598e1a2SLisandro Dalcin numNodes = GmshCellMap[cellType].numNodes; 749730356f6SLisandro Dalcin numTags = entity->numTags; 7509566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numElements, 1, NULL, PETSC_LONG)); 7519566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numElements, PETSC_LONG, 1)); 7529566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, (1 + numNodes) * numElements, sizeof(int), &ibuf)); 7539566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, (1 + numNodes) * numElements, NULL, PETSC_ENUM)); 7549566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, (1 + numNodes) * numElements)); 755de78e4feSLisandro Dalcin for (elem = 0; elem < numElements; ++elem, ++c) { 756de78e4feSLisandro Dalcin GmshElement *element = elements + c; 7570598e1a2SLisandro Dalcin const int *id = ibuf + elem * (1 + numNodes), *nodes = id + 1; 7580598e1a2SLisandro Dalcin element->id = id[0]; 759de78e4feSLisandro Dalcin element->dim = dim; 760de78e4feSLisandro Dalcin element->cellType = cellType; 7610598e1a2SLisandro Dalcin element->numVerts = numVerts; 762de78e4feSLisandro Dalcin element->numNodes = numNodes; 763de78e4feSLisandro Dalcin element->numTags = numTags; 7649566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes)); 7650598e1a2SLisandro Dalcin for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]]; 7660598e1a2SLisandro Dalcin for (p = 0; p < element->numTags; p++) element->tags[p] = entity->tags[p]; 767de78e4feSLisandro Dalcin } 768de78e4feSLisandro Dalcin } 7693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 770698a79b9SLisandro Dalcin } 771698a79b9SLisandro Dalcin 772d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPeriodic_v40(GmshFile *gmsh, PetscInt periodicMap[]) 773d71ae5a4SJacob Faibussowitsch { 774698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 775698a79b9SLisandro Dalcin int fileFormat = gmsh->fileFormat; 776698a79b9SLisandro Dalcin PetscBool binary = gmsh->binary; 777698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 778698a79b9SLisandro Dalcin int numPeriodic, snum, i; 779698a79b9SLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 7800598e1a2SLisandro Dalcin PetscInt *nodeMap = gmsh->nodeMap; 781698a79b9SLisandro Dalcin 782698a79b9SLisandro Dalcin PetscFunctionBegin; 783698a79b9SLisandro Dalcin if (fileFormat == 22 || !binary) { 7849566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 785698a79b9SLisandro Dalcin snum = sscanf(line, "%d", &numPeriodic); 78608401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 787698a79b9SLisandro Dalcin } else { 7889566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numPeriodic, 1, NULL, PETSC_ENUM)); 7899566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numPeriodic, PETSC_ENUM, 1)); 790698a79b9SLisandro Dalcin } 791698a79b9SLisandro Dalcin for (i = 0; i < numPeriodic; i++) { 7929dddd249SSatish Balay int ibuf[3], correspondingDim = -1, correspondingTag = -1, primaryTag = -1, correspondingNode, primaryNode; 793698a79b9SLisandro Dalcin long j, nNodes; 794698a79b9SLisandro Dalcin double affine[16]; 795698a79b9SLisandro Dalcin 796698a79b9SLisandro Dalcin if (fileFormat == 22 || !binary) { 7979566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 3, NULL, PETSC_STRING)); 7989dddd249SSatish Balay snum = sscanf(line, "%d %d %d", &correspondingDim, &correspondingTag, &primaryTag); 79908401ef6SPierre Jolivet PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 800698a79b9SLisandro Dalcin } else { 8019566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM)); 8029566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, 3)); 8039371c9d4SSatish Balay correspondingDim = ibuf[0]; 8049371c9d4SSatish Balay correspondingTag = ibuf[1]; 8059371c9d4SSatish Balay primaryTag = ibuf[2]; 806698a79b9SLisandro Dalcin } 8079371c9d4SSatish Balay (void)correspondingDim; 8089371c9d4SSatish Balay (void)correspondingTag; 8099371c9d4SSatish Balay (void)primaryTag; /* unused */ 810698a79b9SLisandro Dalcin 811698a79b9SLisandro Dalcin if (fileFormat == 22 || !binary) { 8129566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 813698a79b9SLisandro Dalcin snum = sscanf(line, "%ld", &nNodes); 8144c500f23SPierre Jolivet if (snum != 1) { /* discard transformation and try again */ 8159566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, -PETSC_MAX_PATH_LEN, NULL, PETSC_STRING)); 8169566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 817698a79b9SLisandro Dalcin snum = sscanf(line, "%ld", &nNodes); 81808401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 819698a79b9SLisandro Dalcin } 820698a79b9SLisandro Dalcin } else { 8219566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &nNodes, 1, NULL, PETSC_LONG)); 8229566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nNodes, PETSC_LONG, 1)); 8234c500f23SPierre Jolivet if (nNodes == -1) { /* discard transformation and try again */ 8249566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, affine, 16, NULL, PETSC_DOUBLE)); 8259566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &nNodes, 1, NULL, PETSC_LONG)); 8269566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nNodes, PETSC_LONG, 1)); 827698a79b9SLisandro Dalcin } 828698a79b9SLisandro Dalcin } 829698a79b9SLisandro Dalcin 830698a79b9SLisandro Dalcin for (j = 0; j < nNodes; j++) { 831698a79b9SLisandro Dalcin if (fileFormat == 22 || !binary) { 8329566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 2, NULL, PETSC_STRING)); 8339dddd249SSatish Balay snum = sscanf(line, "%d %d", &correspondingNode, &primaryNode); 83408401ef6SPierre Jolivet PetscCheck(snum == 2, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 835698a79b9SLisandro Dalcin } else { 8369566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, 2, NULL, PETSC_ENUM)); 8379566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, 2)); 8389371c9d4SSatish Balay correspondingNode = ibuf[0]; 8399371c9d4SSatish Balay primaryNode = ibuf[1]; 840698a79b9SLisandro Dalcin } 8419dddd249SSatish Balay correspondingNode = (int)nodeMap[correspondingNode]; 8429dddd249SSatish Balay primaryNode = (int)nodeMap[primaryNode]; 8439dddd249SSatish Balay periodicMap[correspondingNode] = primaryNode; 844698a79b9SLisandro Dalcin } 845698a79b9SLisandro Dalcin } 8463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 847698a79b9SLisandro Dalcin } 848698a79b9SLisandro Dalcin 8490598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 850698a79b9SLisandro Dalcin $Entities 851698a79b9SLisandro Dalcin numPoints(size_t) numCurves(size_t) 852698a79b9SLisandro Dalcin numSurfaces(size_t) numVolumes(size_t) 853698a79b9SLisandro Dalcin pointTag(int) X(double) Y(double) Z(double) 854698a79b9SLisandro Dalcin numPhysicalTags(size_t) physicalTag(int) ... 855698a79b9SLisandro Dalcin ... 856698a79b9SLisandro Dalcin curveTag(int) minX(double) minY(double) minZ(double) 857698a79b9SLisandro Dalcin maxX(double) maxY(double) maxZ(double) 858698a79b9SLisandro Dalcin numPhysicalTags(size_t) physicalTag(int) ... 859698a79b9SLisandro Dalcin numBoundingPoints(size_t) pointTag(int) ... 860698a79b9SLisandro Dalcin ... 861698a79b9SLisandro Dalcin surfaceTag(int) minX(double) minY(double) minZ(double) 862698a79b9SLisandro Dalcin maxX(double) maxY(double) maxZ(double) 863698a79b9SLisandro Dalcin numPhysicalTags(size_t) physicalTag(int) ... 864698a79b9SLisandro Dalcin numBoundingCurves(size_t) curveTag(int) ... 865698a79b9SLisandro Dalcin ... 866698a79b9SLisandro Dalcin volumeTag(int) minX(double) minY(double) minZ(double) 867698a79b9SLisandro Dalcin maxX(double) maxY(double) maxZ(double) 868698a79b9SLisandro Dalcin numPhysicalTags(size_t) physicalTag(int) ... 869698a79b9SLisandro Dalcin numBoundngSurfaces(size_t) surfaceTag(int) ... 870698a79b9SLisandro Dalcin ... 871698a79b9SLisandro Dalcin $EndEntities 872698a79b9SLisandro Dalcin */ 873d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEntities_v41(GmshFile *gmsh, GmshMesh *mesh) 874d71ae5a4SJacob Faibussowitsch { 875698a79b9SLisandro Dalcin PetscInt count[4], index, numTags, i; 876698a79b9SLisandro Dalcin int dim, eid, *tags = NULL; 877698a79b9SLisandro Dalcin GmshEntity *entity = NULL; 878698a79b9SLisandro Dalcin 879698a79b9SLisandro Dalcin PetscFunctionBegin; 8809566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, count, 4)); 8819566063dSJacob Faibussowitsch PetscCall(GmshEntitiesCreate(count, &mesh->entities)); 882698a79b9SLisandro Dalcin for (dim = 0; dim < 4; ++dim) { 883698a79b9SLisandro Dalcin for (index = 0; index < count[dim]; ++index) { 8849566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, &eid, 1)); 8859566063dSJacob Faibussowitsch PetscCall(GmshEntitiesAdd(mesh->entities, (PetscInt)index, dim, eid, &entity)); 8869566063dSJacob Faibussowitsch PetscCall(GmshReadDouble(gmsh, entity->bbox, (dim == 0) ? 3 : 6)); 8879566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, &numTags, 1)); 8889566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, numTags, sizeof(int), &tags)); 8899566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, tags, numTags)); 8909c0edc59SMatthew G. Knepley PetscCheck(numTags <= GMSH_MAX_TAGS, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PETSc currently supports up to %" PetscInt_FMT " tags per entity, not %" PetscInt_FMT, (PetscInt)GMSH_MAX_TAGS, numTags); 8917d5b9244SMatthew G. Knepley entity->numTags = numTags; 892698a79b9SLisandro Dalcin for (i = 0; i < entity->numTags; ++i) entity->tags[i] = tags[i]; 893698a79b9SLisandro Dalcin if (dim == 0) continue; 8949566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, &numTags, 1)); 8959566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, numTags, sizeof(int), &tags)); 8969566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, tags, numTags)); 89781a1af93SMatthew G. Knepley /* Currently, we do not save the ids for the bounding entities */ 898698a79b9SLisandro Dalcin } 899698a79b9SLisandro Dalcin } 9003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 901698a79b9SLisandro Dalcin } 902698a79b9SLisandro Dalcin 90333a088b6SMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 904698a79b9SLisandro Dalcin $Nodes 905698a79b9SLisandro Dalcin numEntityBlocks(size_t) numNodes(size_t) 906698a79b9SLisandro Dalcin minNodeTag(size_t) maxNodeTag(size_t) 907698a79b9SLisandro Dalcin entityDim(int) entityTag(int) parametric(int; 0 or 1) numNodesBlock(size_t) 908698a79b9SLisandro Dalcin nodeTag(size_t) 909698a79b9SLisandro Dalcin ... 910698a79b9SLisandro Dalcin x(double) y(double) z(double) 911698a79b9SLisandro Dalcin < u(double; if parametric and entityDim = 1 or entityDim = 2) > 912698a79b9SLisandro Dalcin < v(double; if parametric and entityDim = 2) > 913698a79b9SLisandro Dalcin ... 914698a79b9SLisandro Dalcin ... 915698a79b9SLisandro Dalcin $EndNodes 916698a79b9SLisandro Dalcin */ 917d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes_v41(GmshFile *gmsh, GmshMesh *mesh) 918d71ae5a4SJacob Faibussowitsch { 91981a1af93SMatthew G. Knepley int info[3], dim, eid, parametric; 9207d5b9244SMatthew G. Knepley PetscInt sizes[4], numEntityBlocks, numTags, t, numNodes, numNodesBlock = 0, block, node, n; 92181a1af93SMatthew G. Knepley GmshEntity *entity = NULL; 9220598e1a2SLisandro Dalcin GmshNodes *nodes; 923698a79b9SLisandro Dalcin 924698a79b9SLisandro Dalcin PetscFunctionBegin; 9259566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, sizes, 4)); 9269371c9d4SSatish Balay numEntityBlocks = sizes[0]; 9279371c9d4SSatish Balay numNodes = sizes[1]; 9289566063dSJacob Faibussowitsch PetscCall(GmshNodesCreate(numNodes, &nodes)); 9290598e1a2SLisandro Dalcin mesh->numNodes = numNodes; 9300598e1a2SLisandro Dalcin mesh->nodelist = nodes; 931698a79b9SLisandro Dalcin for (block = 0, node = 0; block < numEntityBlocks; ++block, node += numNodesBlock) { 9329566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, info, 3)); 9339371c9d4SSatish Balay dim = info[0]; 9349371c9d4SSatish Balay eid = info[1]; 9359371c9d4SSatish Balay parametric = info[2]; 9369566063dSJacob Faibussowitsch PetscCall(GmshEntitiesGet(mesh->entities, dim, eid, &entity)); 9377d5b9244SMatthew G. Knepley numTags = entity->numTags; 93881a1af93SMatthew G. Knepley PetscCheck(!parametric, PETSC_COMM_SELF, PETSC_ERR_SUP, "Parametric coordinates not supported"); 9399566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, &numNodesBlock, 1)); 9409566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, nodes->id + node, numNodesBlock)); 9419566063dSJacob Faibussowitsch PetscCall(GmshReadDouble(gmsh, nodes->xyz + node * 3, numNodesBlock * 3)); 9427d5b9244SMatthew G. Knepley for (n = 0; n < numNodesBlock; ++n) { 9437d5b9244SMatthew G. Knepley PetscInt *tags = &nodes->tag[node * GMSH_MAX_TAGS]; 9447d5b9244SMatthew G. Knepley 9457d5b9244SMatthew G. Knepley for (t = 0; t < numTags; ++t) tags[n * GMSH_MAX_TAGS + t] = entity->tags[t]; 9467d5b9244SMatthew G. Knepley for (t = numTags; t < GMSH_MAX_TAGS; ++t) tags[n * GMSH_MAX_TAGS + t] = -1; 9477d5b9244SMatthew G. Knepley } 948698a79b9SLisandro Dalcin } 9490598e1a2SLisandro Dalcin gmsh->nodeStart = sizes[2]; 9500598e1a2SLisandro Dalcin gmsh->nodeEnd = sizes[3] + 1; 9513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 952698a79b9SLisandro Dalcin } 953698a79b9SLisandro Dalcin 95433a088b6SMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 955698a79b9SLisandro Dalcin $Elements 956698a79b9SLisandro Dalcin numEntityBlocks(size_t) numElements(size_t) 957698a79b9SLisandro Dalcin minElementTag(size_t) maxElementTag(size_t) 958698a79b9SLisandro Dalcin entityDim(int) entityTag(int) elementType(int; see below) numElementsBlock(size_t) 959698a79b9SLisandro Dalcin elementTag(size_t) nodeTag(size_t) ... 960698a79b9SLisandro Dalcin ... 961698a79b9SLisandro Dalcin ... 962698a79b9SLisandro Dalcin $EndElements 963698a79b9SLisandro Dalcin */ 964d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements_v41(GmshFile *gmsh, GmshMesh *mesh) 965d71ae5a4SJacob Faibussowitsch { 9660598e1a2SLisandro Dalcin int info[3], eid, dim, cellType; 9670598e1a2SLisandro Dalcin PetscInt sizes[4], *ibuf = NULL, numEntityBlocks, numElements, numBlockElements, numVerts, numNodes, numTags, block, elem, c, p; 968698a79b9SLisandro Dalcin GmshEntity *entity = NULL; 969698a79b9SLisandro Dalcin GmshElement *elements; 9700598e1a2SLisandro Dalcin PetscInt *nodeMap = gmsh->nodeMap; 971698a79b9SLisandro Dalcin 972698a79b9SLisandro Dalcin PetscFunctionBegin; 9739566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, sizes, 4)); 9749371c9d4SSatish Balay numEntityBlocks = sizes[0]; 9759371c9d4SSatish Balay numElements = sizes[1]; 9769566063dSJacob Faibussowitsch PetscCall(GmshElementsCreate(numElements, &elements)); 9770598e1a2SLisandro Dalcin mesh->numElems = numElements; 9780598e1a2SLisandro Dalcin mesh->elements = elements; 979698a79b9SLisandro Dalcin for (c = 0, block = 0; block < numEntityBlocks; ++block) { 9809566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, info, 3)); 9819371c9d4SSatish Balay dim = info[0]; 9829371c9d4SSatish Balay eid = info[1]; 9839371c9d4SSatish Balay cellType = info[2]; 9849566063dSJacob Faibussowitsch PetscCall(GmshEntitiesGet(mesh->entities, dim, eid, &entity)); 9859566063dSJacob Faibussowitsch PetscCall(GmshCellTypeCheck(cellType)); 9860598e1a2SLisandro Dalcin numVerts = GmshCellMap[cellType].numVerts; 9870598e1a2SLisandro Dalcin numNodes = GmshCellMap[cellType].numNodes; 9887d5b9244SMatthew G. Knepley numTags = entity->numTags; 9899566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, &numBlockElements, 1)); 9909566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, (1 + numNodes) * numBlockElements, sizeof(PetscInt), &ibuf)); 9919566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, ibuf, (1 + numNodes) * numBlockElements)); 992698a79b9SLisandro Dalcin for (elem = 0; elem < numBlockElements; ++elem, ++c) { 993698a79b9SLisandro Dalcin GmshElement *element = elements + c; 9940598e1a2SLisandro Dalcin const PetscInt *id = ibuf + elem * (1 + numNodes), *nodes = id + 1; 995698a79b9SLisandro Dalcin element->id = id[0]; 996698a79b9SLisandro Dalcin element->dim = dim; 997698a79b9SLisandro Dalcin element->cellType = cellType; 9980598e1a2SLisandro Dalcin element->numVerts = numVerts; 999698a79b9SLisandro Dalcin element->numNodes = numNodes; 1000698a79b9SLisandro Dalcin element->numTags = numTags; 10019566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes)); 10020598e1a2SLisandro Dalcin for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]]; 10030598e1a2SLisandro Dalcin for (p = 0; p < element->numTags; p++) element->tags[p] = entity->tags[p]; 1004698a79b9SLisandro Dalcin } 1005698a79b9SLisandro Dalcin } 10063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1007698a79b9SLisandro Dalcin } 1008698a79b9SLisandro Dalcin 10090598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 1010698a79b9SLisandro Dalcin $Periodic 1011698a79b9SLisandro Dalcin numPeriodicLinks(size_t) 10129dddd249SSatish Balay entityDim(int) entityTag(int) entityTagPrimary(int) 1013698a79b9SLisandro Dalcin numAffine(size_t) value(double) ... 1014698a79b9SLisandro Dalcin numCorrespondingNodes(size_t) 10159dddd249SSatish Balay nodeTag(size_t) nodeTagPrimary(size_t) 1016698a79b9SLisandro Dalcin ... 1017698a79b9SLisandro Dalcin ... 1018698a79b9SLisandro Dalcin $EndPeriodic 1019698a79b9SLisandro Dalcin */ 1020d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPeriodic_v41(GmshFile *gmsh, PetscInt periodicMap[]) 1021d71ae5a4SJacob Faibussowitsch { 1022698a79b9SLisandro Dalcin int info[3]; 1023698a79b9SLisandro Dalcin double dbuf[16]; 10240598e1a2SLisandro Dalcin PetscInt numPeriodicLinks, numAffine, numCorrespondingNodes, *nodeTags = NULL, link, node; 10250598e1a2SLisandro Dalcin PetscInt *nodeMap = gmsh->nodeMap; 1026698a79b9SLisandro Dalcin 1027698a79b9SLisandro Dalcin PetscFunctionBegin; 10289566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, &numPeriodicLinks, 1)); 1029698a79b9SLisandro Dalcin for (link = 0; link < numPeriodicLinks; ++link) { 10309566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, info, 3)); 10319566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, &numAffine, 1)); 10329566063dSJacob Faibussowitsch PetscCall(GmshReadDouble(gmsh, dbuf, numAffine)); 10339566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, &numCorrespondingNodes, 1)); 10349566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, numCorrespondingNodes, sizeof(PetscInt), &nodeTags)); 10359566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, nodeTags, numCorrespondingNodes * 2)); 1036698a79b9SLisandro Dalcin for (node = 0; node < numCorrespondingNodes; ++node) { 10379dddd249SSatish Balay PetscInt correspondingNode = nodeMap[nodeTags[node * 2 + 0]]; 10389dddd249SSatish Balay PetscInt primaryNode = nodeMap[nodeTags[node * 2 + 1]]; 10399dddd249SSatish Balay periodicMap[correspondingNode] = primaryNode; 1040698a79b9SLisandro Dalcin } 1041698a79b9SLisandro Dalcin } 10423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1043698a79b9SLisandro Dalcin } 1044698a79b9SLisandro Dalcin 10450598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 1046d6689ca9SLisandro Dalcin $MeshFormat // same as MSH version 2 1047d6689ca9SLisandro Dalcin version(ASCII double; currently 4.1) 1048d6689ca9SLisandro Dalcin file-type(ASCII int; 0 for ASCII mode, 1 for binary mode) 1049d6689ca9SLisandro Dalcin data-size(ASCII int; sizeof(size_t)) 1050d6689ca9SLisandro Dalcin < int with value one; only in binary mode, to detect endianness > 1051d6689ca9SLisandro Dalcin $EndMeshFormat 1052d6689ca9SLisandro Dalcin */ 1053d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadMeshFormat(GmshFile *gmsh) 1054d71ae5a4SJacob Faibussowitsch { 1055698a79b9SLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 1056698a79b9SLisandro Dalcin int snum, fileType, fileFormat, dataSize, checkEndian; 1057698a79b9SLisandro Dalcin float version; 1058698a79b9SLisandro Dalcin 1059698a79b9SLisandro Dalcin PetscFunctionBegin; 10609566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 3)); 1061698a79b9SLisandro Dalcin snum = sscanf(line, "%f %d %d", &version, &fileType, &dataSize); 1062a8d4e440SJunchao Zhang fileFormat = (int)roundf(version * 10); 106308401ef6SPierre Jolivet PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line); 1064a8d4e440SJunchao Zhang PetscCheck(fileFormat >= 22, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at least 2.2", (double)version); 10651dca8a05SBarry Smith PetscCheck((int)version != 3, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f not supported", (double)version); 1066a8d4e440SJunchao Zhang PetscCheck(fileFormat <= 41, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at most 4.1", (double)version); 106708401ef6SPierre Jolivet PetscCheck(!gmsh->binary || fileType, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Viewer is binary but Gmsh file is ASCII"); 106808401ef6SPierre Jolivet PetscCheck(gmsh->binary || !fileType, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Viewer is ASCII but Gmsh file is binary"); 10691dca8a05SBarry Smith PetscCheck(fileFormat > 40 || dataSize == sizeof(double), PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Data size %d is not valid for a Gmsh file", dataSize); 10701dca8a05SBarry Smith PetscCheck(fileFormat < 41 || dataSize == sizeof(int) || dataSize == sizeof(PetscInt64), PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Data size %d is not valid for a Gmsh file", dataSize); 1071698a79b9SLisandro Dalcin gmsh->fileFormat = fileFormat; 1072698a79b9SLisandro Dalcin gmsh->dataSize = dataSize; 1073698a79b9SLisandro Dalcin gmsh->byteSwap = PETSC_FALSE; 1074698a79b9SLisandro Dalcin if (gmsh->binary) { 10759566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, &checkEndian, 1)); 1076698a79b9SLisandro Dalcin if (checkEndian != 1) { 10779566063dSJacob Faibussowitsch PetscCall(PetscByteSwap(&checkEndian, PETSC_ENUM, 1)); 107808401ef6SPierre Jolivet PetscCheck(checkEndian == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to detect endianness in Gmsh file header: %s", line); 1079698a79b9SLisandro Dalcin gmsh->byteSwap = PETSC_TRUE; 1080698a79b9SLisandro Dalcin } 1081698a79b9SLisandro Dalcin } 10823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1083698a79b9SLisandro Dalcin } 1084698a79b9SLisandro Dalcin 10851f643af3SLisandro Dalcin /* 10861f643af3SLisandro Dalcin PhysicalNames 10871f643af3SLisandro Dalcin numPhysicalNames(ASCII int) 10881f643af3SLisandro Dalcin dimension(ASCII int) physicalTag(ASCII int) "name"(127 characters max) 10891f643af3SLisandro Dalcin ... 10901f643af3SLisandro Dalcin $EndPhysicalNames 10911f643af3SLisandro Dalcin */ 1092d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPhysicalNames(GmshFile *gmsh, GmshMesh *mesh) 1093d71ae5a4SJacob Faibussowitsch { 1094bbcf679cSJacob Faibussowitsch char line[PETSC_MAX_PATH_LEN], name[128 + 2], *p = NULL, *q = NULL, *r = NULL; 1095a45dabc8SMatthew G. Knepley int snum, region, dim, tag; 1096698a79b9SLisandro Dalcin 1097698a79b9SLisandro Dalcin PetscFunctionBegin; 10989566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 1)); 1099a45dabc8SMatthew G. Knepley snum = sscanf(line, "%d", ®ion); 1100a45dabc8SMatthew G. Knepley mesh->numRegions = region; 110108401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 110290d778b8SLisandro Dalcin PetscCall(PetscMalloc3(mesh->numRegions, &mesh->regionDims, mesh->numRegions, &mesh->regionTags, mesh->numRegions, &mesh->regionNames)); 1103a45dabc8SMatthew G. Knepley for (region = 0; region < mesh->numRegions; ++region) { 11049566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 2)); 11051f643af3SLisandro Dalcin snum = sscanf(line, "%d %d", &dim, &tag); 110608401ef6SPierre Jolivet PetscCheck(snum == 2, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 11079566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, -(PetscInt)sizeof(line))); 11089566063dSJacob Faibussowitsch PetscCall(PetscStrchr(line, '"', &p)); 110928b400f6SJacob Faibussowitsch PetscCheck(p, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 11109566063dSJacob Faibussowitsch PetscCall(PetscStrrchr(line, '"', &q)); 111108401ef6SPierre Jolivet PetscCheck(q != p, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 11125f5cd6d5SMatthew G. Knepley PetscCall(PetscStrrchr(line, ':', &r)); 11135f5cd6d5SMatthew G. Knepley if (p != r) q = r; 11149566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(name, p + 1, (size_t)(q - p - 1))); 111590d778b8SLisandro Dalcin mesh->regionDims[region] = dim; 1116a45dabc8SMatthew G. Knepley mesh->regionTags[region] = tag; 11179566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(name, &mesh->regionNames[region])); 1118698a79b9SLisandro Dalcin } 11193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1120de78e4feSLisandro Dalcin } 1121de78e4feSLisandro Dalcin 1122d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEntities(GmshFile *gmsh, GmshMesh *mesh) 1123d71ae5a4SJacob Faibussowitsch { 11240598e1a2SLisandro Dalcin PetscFunctionBegin; 11250598e1a2SLisandro Dalcin switch (gmsh->fileFormat) { 1126d71ae5a4SJacob Faibussowitsch case 41: 1127d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadEntities_v41(gmsh, mesh)); 1128d71ae5a4SJacob Faibussowitsch break; 1129d71ae5a4SJacob Faibussowitsch default: 1130d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadEntities_v40(gmsh, mesh)); 1131d71ae5a4SJacob Faibussowitsch break; 113296ca5757SLisandro Dalcin } 11333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11340598e1a2SLisandro Dalcin } 11350598e1a2SLisandro Dalcin 1136d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes(GmshFile *gmsh, GmshMesh *mesh) 1137d71ae5a4SJacob Faibussowitsch { 11380598e1a2SLisandro Dalcin PetscFunctionBegin; 11390598e1a2SLisandro Dalcin switch (gmsh->fileFormat) { 1140d71ae5a4SJacob Faibussowitsch case 41: 1141d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadNodes_v41(gmsh, mesh)); 1142d71ae5a4SJacob Faibussowitsch break; 1143d71ae5a4SJacob Faibussowitsch case 40: 1144d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadNodes_v40(gmsh, mesh)); 1145d71ae5a4SJacob Faibussowitsch break; 1146d71ae5a4SJacob Faibussowitsch default: 1147d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadNodes_v22(gmsh, mesh)); 1148d71ae5a4SJacob Faibussowitsch break; 11490598e1a2SLisandro Dalcin } 11500598e1a2SLisandro Dalcin 11510598e1a2SLisandro Dalcin { /* Gmsh v2.2/v4.0 does not provide min/max node tags */ 11520598e1a2SLisandro Dalcin if (mesh->numNodes > 0 && gmsh->nodeEnd >= gmsh->nodeStart) { 11530598e1a2SLisandro Dalcin PetscInt tagMin = PETSC_MAX_INT, tagMax = PETSC_MIN_INT, n; 11540598e1a2SLisandro Dalcin GmshNodes *nodes = mesh->nodelist; 11550598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) { 11560598e1a2SLisandro Dalcin const PetscInt tag = nodes->id[n]; 11570598e1a2SLisandro Dalcin tagMin = PetscMin(tag, tagMin); 11580598e1a2SLisandro Dalcin tagMax = PetscMax(tag, tagMax); 11590598e1a2SLisandro Dalcin } 11600598e1a2SLisandro Dalcin gmsh->nodeStart = tagMin; 11610598e1a2SLisandro Dalcin gmsh->nodeEnd = tagMax + 1; 11620598e1a2SLisandro Dalcin } 11630598e1a2SLisandro Dalcin } 11640598e1a2SLisandro Dalcin 11650598e1a2SLisandro Dalcin { /* Support for sparse node tags */ 11660598e1a2SLisandro Dalcin PetscInt n, t; 11670598e1a2SLisandro Dalcin GmshNodes *nodes = mesh->nodelist; 11689566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(gmsh->nodeEnd - gmsh->nodeStart, &gmsh->nbuf)); 11690598e1a2SLisandro Dalcin for (t = 0; t < gmsh->nodeEnd - gmsh->nodeStart; ++t) gmsh->nbuf[t] = PETSC_MIN_INT; 11700598e1a2SLisandro Dalcin gmsh->nodeMap = gmsh->nbuf - gmsh->nodeStart; 11710598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) { 11720598e1a2SLisandro Dalcin const PetscInt tag = nodes->id[n]; 117363a3b9bcSJacob Faibussowitsch PetscCheck(gmsh->nodeMap[tag] < 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Repeated node tag %" PetscInt_FMT, tag); 11740598e1a2SLisandro Dalcin gmsh->nodeMap[tag] = n; 11750598e1a2SLisandro Dalcin } 11760598e1a2SLisandro Dalcin } 11773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11780598e1a2SLisandro Dalcin } 11790598e1a2SLisandro Dalcin 1180d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements(GmshFile *gmsh, GmshMesh *mesh) 1181d71ae5a4SJacob Faibussowitsch { 11820598e1a2SLisandro Dalcin PetscFunctionBegin; 11830598e1a2SLisandro Dalcin switch (gmsh->fileFormat) { 1184d71ae5a4SJacob Faibussowitsch case 41: 1185d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadElements_v41(gmsh, mesh)); 1186d71ae5a4SJacob Faibussowitsch break; 1187d71ae5a4SJacob Faibussowitsch case 40: 1188d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadElements_v40(gmsh, mesh)); 1189d71ae5a4SJacob Faibussowitsch break; 1190d71ae5a4SJacob Faibussowitsch default: 1191d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadElements_v22(gmsh, mesh)); 1192d71ae5a4SJacob Faibussowitsch break; 11930598e1a2SLisandro Dalcin } 11940598e1a2SLisandro Dalcin 11950598e1a2SLisandro Dalcin { /* Reorder elements by codimension and polytope type */ 11960598e1a2SLisandro Dalcin PetscInt ne = mesh->numElems; 11970598e1a2SLisandro Dalcin GmshElement *elements = mesh->elements; 1198066ea43fSLisandro Dalcin PetscInt keymap[GMSH_NUM_POLYTOPES], nk = 0; 1199066ea43fSLisandro Dalcin PetscInt offset[GMSH_NUM_POLYTOPES + 1], e, k; 12000598e1a2SLisandro Dalcin 1201066ea43fSLisandro Dalcin for (k = 0; k < GMSH_NUM_POLYTOPES; ++k) keymap[k] = PETSC_MIN_INT; 12029566063dSJacob Faibussowitsch PetscCall(PetscMemzero(offset, sizeof(offset))); 12030598e1a2SLisandro Dalcin 1204066ea43fSLisandro Dalcin keymap[GMSH_TET] = nk++; 1205066ea43fSLisandro Dalcin keymap[GMSH_HEX] = nk++; 1206066ea43fSLisandro Dalcin keymap[GMSH_PRI] = nk++; 1207066ea43fSLisandro Dalcin keymap[GMSH_PYR] = nk++; 1208066ea43fSLisandro Dalcin keymap[GMSH_TRI] = nk++; 1209066ea43fSLisandro Dalcin keymap[GMSH_QUA] = nk++; 1210066ea43fSLisandro Dalcin keymap[GMSH_SEG] = nk++; 1211066ea43fSLisandro Dalcin keymap[GMSH_VTX] = nk++; 12120598e1a2SLisandro Dalcin 12139566063dSJacob Faibussowitsch PetscCall(GmshElementsCreate(mesh->numElems, &mesh->elements)); 12140598e1a2SLisandro Dalcin #define key(eid) keymap[GmshCellMap[elements[(eid)].cellType].polytope] 12150598e1a2SLisandro Dalcin for (e = 0; e < ne; ++e) offset[1 + key(e)]++; 12160598e1a2SLisandro Dalcin for (k = 1; k < nk; ++k) offset[k] += offset[k - 1]; 12170598e1a2SLisandro Dalcin for (e = 0; e < ne; ++e) mesh->elements[offset[key(e)]++] = elements[e]; 12180598e1a2SLisandro Dalcin #undef key 12199566063dSJacob Faibussowitsch PetscCall(GmshElementsDestroy(&elements)); 1220066ea43fSLisandro Dalcin } 12210598e1a2SLisandro Dalcin 1222066ea43fSLisandro Dalcin { /* Mesh dimension and order */ 1223066ea43fSLisandro Dalcin GmshElement *elem = mesh->numElems ? mesh->elements : NULL; 1224066ea43fSLisandro Dalcin mesh->dim = elem ? GmshCellMap[elem->cellType].dim : 0; 1225066ea43fSLisandro Dalcin mesh->order = elem ? GmshCellMap[elem->cellType].order : 0; 12260598e1a2SLisandro Dalcin } 12270598e1a2SLisandro Dalcin 12280598e1a2SLisandro Dalcin { 12290598e1a2SLisandro Dalcin PetscBT vtx; 12300598e1a2SLisandro Dalcin PetscInt dim = mesh->dim, e, n, v; 12310598e1a2SLisandro Dalcin 12329566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(mesh->numNodes, &vtx)); 12330598e1a2SLisandro Dalcin 12340598e1a2SLisandro Dalcin /* Compute number of cells and set of vertices */ 12350598e1a2SLisandro Dalcin mesh->numCells = 0; 12360598e1a2SLisandro Dalcin for (e = 0; e < mesh->numElems; ++e) { 12370598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + e; 12380598e1a2SLisandro Dalcin if (elem->dim == dim && dim > 0) mesh->numCells++; 123948a46eb9SPierre Jolivet for (v = 0; v < elem->numVerts; v++) PetscCall(PetscBTSet(vtx, elem->nodes[v])); 12400598e1a2SLisandro Dalcin } 12410598e1a2SLisandro Dalcin 12420598e1a2SLisandro Dalcin /* Compute numbering for vertices */ 12430598e1a2SLisandro Dalcin mesh->numVerts = 0; 12449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mesh->numNodes, &mesh->vertexMap)); 12459371c9d4SSatish Balay for (n = 0; n < mesh->numNodes; ++n) mesh->vertexMap[n] = PetscBTLookup(vtx, n) ? mesh->numVerts++ : PETSC_MIN_INT; 12460598e1a2SLisandro Dalcin 12479566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&vtx)); 12480598e1a2SLisandro Dalcin } 12493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12500598e1a2SLisandro Dalcin } 12510598e1a2SLisandro Dalcin 1252d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPeriodic(GmshFile *gmsh, GmshMesh *mesh) 1253d71ae5a4SJacob Faibussowitsch { 12540598e1a2SLisandro Dalcin PetscInt n; 12550598e1a2SLisandro Dalcin 12560598e1a2SLisandro Dalcin PetscFunctionBegin; 12579566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mesh->numNodes, &mesh->periodMap)); 12580598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) mesh->periodMap[n] = n; 12590598e1a2SLisandro Dalcin switch (gmsh->fileFormat) { 1260d71ae5a4SJacob Faibussowitsch case 41: 1261d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadPeriodic_v41(gmsh, mesh->periodMap)); 1262d71ae5a4SJacob Faibussowitsch break; 1263d71ae5a4SJacob Faibussowitsch default: 1264d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadPeriodic_v40(gmsh, mesh->periodMap)); 1265d71ae5a4SJacob Faibussowitsch break; 12660598e1a2SLisandro Dalcin } 12670598e1a2SLisandro Dalcin 12689dddd249SSatish Balay /* Find canonical primary nodes */ 12690598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) 12709371c9d4SSatish Balay while (mesh->periodMap[n] != mesh->periodMap[mesh->periodMap[n]]) mesh->periodMap[n] = mesh->periodMap[mesh->periodMap[n]]; 12710598e1a2SLisandro Dalcin 12729dddd249SSatish Balay /* Renumber vertices (filter out correspondings) */ 12730598e1a2SLisandro Dalcin mesh->numVerts = 0; 12740598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) 12750598e1a2SLisandro Dalcin if (mesh->vertexMap[n] >= 0) /* is vertex */ 12769dddd249SSatish Balay if (mesh->periodMap[n] == n) /* is primary */ 12770598e1a2SLisandro Dalcin mesh->vertexMap[n] = mesh->numVerts++; 12780598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) 12790598e1a2SLisandro Dalcin if (mesh->vertexMap[n] >= 0) /* is vertex */ 12809dddd249SSatish Balay if (mesh->periodMap[n] != n) /* is corresponding */ 12810598e1a2SLisandro Dalcin mesh->vertexMap[n] = mesh->vertexMap[mesh->periodMap[n]]; 12823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12830598e1a2SLisandro Dalcin } 12840598e1a2SLisandro Dalcin 1285066ea43fSLisandro Dalcin #define DM_POLYTOPE_VERTEX DM_POLYTOPE_POINT 1286066ea43fSLisandro Dalcin static const DMPolytopeType DMPolytopeMap[] = { 1287066ea43fSLisandro Dalcin /* GMSH_VTX */ DM_POLYTOPE_VERTEX, 1288066ea43fSLisandro Dalcin /* GMSH_SEG */ DM_POLYTOPE_SEGMENT, 1289066ea43fSLisandro Dalcin /* GMSH_TRI */ DM_POLYTOPE_TRIANGLE, 1290066ea43fSLisandro Dalcin /* GMSH_QUA */ DM_POLYTOPE_QUADRILATERAL, 1291066ea43fSLisandro Dalcin /* GMSH_TET */ DM_POLYTOPE_TETRAHEDRON, 1292066ea43fSLisandro Dalcin /* GMSH_HEX */ DM_POLYTOPE_HEXAHEDRON, 1293066ea43fSLisandro Dalcin /* GMSH_PRI */ DM_POLYTOPE_TRI_PRISM, 12949371c9d4SSatish Balay /* GMSH_PYR */ DM_POLYTOPE_PYRAMID, DM_POLYTOPE_UNKNOWN}; 12950598e1a2SLisandro Dalcin 1296d71ae5a4SJacob Faibussowitsch static inline DMPolytopeType DMPolytopeTypeFromGmsh(PetscInt cellType) 1297d71ae5a4SJacob Faibussowitsch { 1298066ea43fSLisandro Dalcin return DMPolytopeMap[GmshCellMap[cellType].polytope]; 1299066ea43fSLisandro Dalcin } 1300066ea43fSLisandro Dalcin 1301d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshCreateFE(MPI_Comm comm, const char prefix[], PetscBool isSimplex, PetscBool continuity, PetscDTNodeType nodeType, PetscInt dim, PetscInt Nc, PetscInt k, PetscFE *fem) 1302d71ae5a4SJacob Faibussowitsch { 1303066ea43fSLisandro Dalcin DM K; 1304066ea43fSLisandro Dalcin PetscSpace P; 1305066ea43fSLisandro Dalcin PetscDualSpace Q; 1306066ea43fSLisandro Dalcin PetscQuadrature q, fq; 1307066ea43fSLisandro Dalcin PetscBool isTensor = isSimplex ? PETSC_FALSE : PETSC_TRUE; 1308066ea43fSLisandro Dalcin PetscBool endpoint = PETSC_TRUE; 1309066ea43fSLisandro Dalcin char name[32]; 1310066ea43fSLisandro Dalcin 1311066ea43fSLisandro Dalcin PetscFunctionBegin; 1312066ea43fSLisandro Dalcin /* Create space */ 13139566063dSJacob Faibussowitsch PetscCall(PetscSpaceCreate(comm, &P)); 13149566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetType(P, PETSCSPACEPOLYNOMIAL)); 13159566063dSJacob Faibussowitsch PetscCall(PetscSpacePolynomialSetTensor(P, isTensor)); 13169566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumComponents(P, Nc)); 13179566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumVariables(P, dim)); 13189566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetDegree(P, k, PETSC_DETERMINE)); 1319066ea43fSLisandro Dalcin if (prefix) { 13209566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)P, prefix)); 13219566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetFromOptions(P)); 13229566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)P, NULL)); 13239566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetDegree(P, &k, NULL)); 1324066ea43fSLisandro Dalcin } 13259566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetUp(P)); 1326066ea43fSLisandro Dalcin /* Create dual space */ 13279566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceCreate(comm, &Q)); 13289566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetType(Q, PETSCDUALSPACELAGRANGE)); 13299566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceLagrangeSetTensor(Q, isTensor)); 13309566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceLagrangeSetContinuity(Q, continuity)); 13319566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceLagrangeSetNodeType(Q, nodeType, endpoint, 0)); 13329566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetNumComponents(Q, Nc)); 13339566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetOrder(Q, k)); 13349566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell(PETSC_COMM_SELF, DMPolytopeTypeSimpleShape(dim, isSimplex), &K)); 13359566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetDM(Q, K)); 13369566063dSJacob Faibussowitsch PetscCall(DMDestroy(&K)); 1337066ea43fSLisandro Dalcin if (prefix) { 13389566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)Q, prefix)); 13399566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetFromOptions(Q)); 13409566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)Q, NULL)); 1341066ea43fSLisandro Dalcin } 13429566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetUp(Q)); 1343066ea43fSLisandro Dalcin /* Create quadrature */ 1344066ea43fSLisandro Dalcin if (isSimplex) { 13459566063dSJacob Faibussowitsch PetscCall(PetscDTStroudConicalQuadrature(dim, 1, k + 1, -1, +1, &q)); 13469566063dSJacob Faibussowitsch PetscCall(PetscDTStroudConicalQuadrature(dim - 1, 1, k + 1, -1, +1, &fq)); 1347066ea43fSLisandro Dalcin } else { 13489566063dSJacob Faibussowitsch PetscCall(PetscDTGaussTensorQuadrature(dim, 1, k + 1, -1, +1, &q)); 13499566063dSJacob Faibussowitsch PetscCall(PetscDTGaussTensorQuadrature(dim - 1, 1, k + 1, -1, +1, &fq)); 1350066ea43fSLisandro Dalcin } 1351066ea43fSLisandro Dalcin /* Create finite element */ 13529566063dSJacob Faibussowitsch PetscCall(PetscFECreate(comm, fem)); 13539566063dSJacob Faibussowitsch PetscCall(PetscFESetType(*fem, PETSCFEBASIC)); 13549566063dSJacob Faibussowitsch PetscCall(PetscFESetNumComponents(*fem, Nc)); 13559566063dSJacob Faibussowitsch PetscCall(PetscFESetBasisSpace(*fem, P)); 13569566063dSJacob Faibussowitsch PetscCall(PetscFESetDualSpace(*fem, Q)); 13579566063dSJacob Faibussowitsch PetscCall(PetscFESetQuadrature(*fem, q)); 13589566063dSJacob Faibussowitsch PetscCall(PetscFESetFaceQuadrature(*fem, fq)); 1359066ea43fSLisandro Dalcin if (prefix) { 13609566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*fem, prefix)); 13619566063dSJacob Faibussowitsch PetscCall(PetscFESetFromOptions(*fem)); 13629566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*fem, NULL)); 1363066ea43fSLisandro Dalcin } 13649566063dSJacob Faibussowitsch PetscCall(PetscFESetUp(*fem)); 1365066ea43fSLisandro Dalcin /* Cleanup */ 13669566063dSJacob Faibussowitsch PetscCall(PetscSpaceDestroy(&P)); 13679566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceDestroy(&Q)); 13689566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&q)); 13699566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&fq)); 1370066ea43fSLisandro Dalcin /* Set finite element name */ 137163a3b9bcSJacob Faibussowitsch PetscCall(PetscSNPrintf(name, sizeof(name), "%s%" PetscInt_FMT, isSimplex ? "P" : "Q", k)); 13729566063dSJacob Faibussowitsch PetscCall(PetscFESetName(*fem, name)); 13733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 137496ca5757SLisandro Dalcin } 137596ca5757SLisandro Dalcin 1376d6689ca9SLisandro Dalcin /*@C 1377a1cb98faSBarry Smith DMPlexCreateGmshFromFile - Create a `DMPLEX` mesh from a Gmsh file 1378d6689ca9SLisandro Dalcin 1379*a4e35b19SJacob Faibussowitsch Input Parameters: 1380d6689ca9SLisandro Dalcin + comm - The MPI communicator 1381d6689ca9SLisandro Dalcin . filename - Name of the Gmsh file 1382d6689ca9SLisandro Dalcin - interpolate - Create faces and edges in the mesh 1383d6689ca9SLisandro Dalcin 1384d6689ca9SLisandro Dalcin Output Parameter: 1385a1cb98faSBarry Smith . dm - The `DM` object representing the mesh 1386d6689ca9SLisandro Dalcin 1387d6689ca9SLisandro Dalcin Level: beginner 1388d6689ca9SLisandro Dalcin 13891cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()` 1390d6689ca9SLisandro Dalcin @*/ 1391d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateGmshFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) 1392d71ae5a4SJacob Faibussowitsch { 1393d6689ca9SLisandro Dalcin PetscViewer viewer; 1394d6689ca9SLisandro Dalcin PetscMPIInt rank; 1395d6689ca9SLisandro Dalcin int fileType; 1396d6689ca9SLisandro Dalcin PetscViewerType vtype; 1397d6689ca9SLisandro Dalcin 1398d6689ca9SLisandro Dalcin PetscFunctionBegin; 13999566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1400d6689ca9SLisandro Dalcin 1401d6689ca9SLisandro Dalcin /* Determine Gmsh file type (ASCII or binary) from file header */ 1402dd400576SPatrick Sanan if (rank == 0) { 14030598e1a2SLisandro Dalcin GmshFile gmsh[1]; 1404d6689ca9SLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 1405d6689ca9SLisandro Dalcin int snum; 1406d6689ca9SLisandro Dalcin float version; 1407a8d4e440SJunchao Zhang int fileFormat; 1408d6689ca9SLisandro Dalcin 14099566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(gmsh, 1)); 14109566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(PETSC_COMM_SELF, &gmsh->viewer)); 14119566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(gmsh->viewer, PETSCVIEWERASCII)); 14129566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(gmsh->viewer, FILE_MODE_READ)); 14139566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(gmsh->viewer, filename)); 1414d6689ca9SLisandro Dalcin /* Read only the first two lines of the Gmsh file */ 14159566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 14169566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$MeshFormat", line)); 14179566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 2)); 1418d6689ca9SLisandro Dalcin snum = sscanf(line, "%f %d", &version, &fileType); 1419a8d4e440SJunchao Zhang fileFormat = (int)roundf(version * 10); 142008401ef6SPierre Jolivet PetscCheck(snum == 2, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line); 1421a8d4e440SJunchao Zhang PetscCheck(fileFormat >= 22, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at least 2.2", (double)version); 14221dca8a05SBarry Smith PetscCheck((int)version != 3, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f not supported", (double)version); 1423a8d4e440SJunchao Zhang PetscCheck(fileFormat <= 41, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at most 4.1", (double)version); 14249566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&gmsh->viewer)); 1425d6689ca9SLisandro Dalcin } 14269566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&fileType, 1, MPI_INT, 0, comm)); 1427d6689ca9SLisandro Dalcin vtype = (fileType == 0) ? PETSCVIEWERASCII : PETSCVIEWERBINARY; 1428d6689ca9SLisandro Dalcin 1429d6689ca9SLisandro Dalcin /* Create appropriate viewer and build plex */ 14309566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 14319566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, vtype)); 14329566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 14339566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 14349566063dSJacob Faibussowitsch PetscCall(DMPlexCreateGmsh(comm, viewer, interpolate, dm)); 14359566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 14363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1437d6689ca9SLisandro Dalcin } 1438d6689ca9SLisandro Dalcin 1439331830f3SMatthew G. Knepley /*@ 1440a1cb98faSBarry Smith DMPlexCreateGmsh - Create a `DMPLEX` mesh from a Gmsh file viewer 1441331830f3SMatthew G. Knepley 1442d083f849SBarry Smith Collective 1443331830f3SMatthew G. Knepley 1444331830f3SMatthew G. Knepley Input Parameters: 1445331830f3SMatthew G. Knepley + comm - The MPI communicator 1446a1cb98faSBarry Smith . viewer - The `PetscViewer` associated with a Gmsh file 1447331830f3SMatthew G. Knepley - interpolate - Create faces and edges in the mesh 1448331830f3SMatthew G. Knepley 1449331830f3SMatthew G. Knepley Output Parameter: 1450a1cb98faSBarry Smith . dm - The `DM` object representing the mesh 1451331830f3SMatthew G. Knepley 1452a1cb98faSBarry Smith Options Database Keys: 1453df93260fSMatthew G. Knepley + -dm_plex_gmsh_hybrid - Force triangular prisms to use tensor order 1454df93260fSMatthew G. Knepley . -dm_plex_gmsh_periodic - Read Gmsh periodic section and construct a periodic Plex 1455df93260fSMatthew G. Knepley . -dm_plex_gmsh_highorder - Generate high-order coordinates 1456df93260fSMatthew 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 1457df93260fSMatthew G. Knepley . -dm_plex_gmsh_use_regions - Generate labels with region names 1458df93260fSMatthew G. Knepley . -dm_plex_gmsh_mark_vertices - Add vertices to generated labels 1459df93260fSMatthew G. Knepley . -dm_plex_gmsh_multiple_tags - Allow multiple tags for default labels 1460df93260fSMatthew G. Knepley - -dm_plex_gmsh_spacedim <d> - Embedding space dimension, if different from topological dimension 1461df93260fSMatthew G. Knepley 1462df93260fSMatthew G. Knepley Note: 1463df93260fSMatthew G. Knepley The Gmsh file format is described in http://gmsh.info/doc/texinfo/gmsh.html#MSH-file-format 1464df93260fSMatthew G. Knepley 1465df93260fSMatthew G. Knepley By default, the "Cell Sets", "Face Sets", and "Vertex Sets" labels are created, and only insert the first tag on a point. By using -dm_plex_gmsh_multiple_tags, all tags can be inserted. Instead, -dm_plex_gmsh_use_regions creates labels based on the region names from the PhysicalNames section, and all tags are used. 1466331830f3SMatthew G. Knepley 1467331830f3SMatthew G. Knepley Level: beginner 1468331830f3SMatthew G. Knepley 14691cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()` 1470331830f3SMatthew G. Knepley @*/ 1471d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateGmsh(MPI_Comm comm, PetscViewer viewer, PetscBool interpolate, DM *dm) 1472d71ae5a4SJacob Faibussowitsch { 14730598e1a2SLisandro Dalcin GmshMesh *mesh = NULL; 147411c56cb0SLisandro Dalcin PetscViewer parentviewer = NULL; 14750598e1a2SLisandro Dalcin PetscBT periodicVerts = NULL; 1476eae3dc7dSJacob Faibussowitsch PetscBT *periodicCells = NULL; 14776858538eSMatthew G. Knepley DM cdm, cdmCell = NULL; 14786858538eSMatthew G. Knepley PetscSection cs, csCell = NULL; 14796858538eSMatthew G. Knepley Vec coordinates, coordinatesCell; 1480a45dabc8SMatthew G. Knepley DMLabel cellSets = NULL, faceSets = NULL, vertSets = NULL, marker = NULL, *regionSets; 14819db5b827SMatthew G. Knepley PetscInt dim = 0, coordDim = -1, order = 0, maxHeight = 0; 14829db5b827SMatthew G. Knepley PetscInt numNodes = 0, numElems = 0, numVerts = 0, numCells = 0, vStart, vEnd; 1483066ea43fSLisandro Dalcin PetscInt cell, cone[8], e, n, v, d; 1484df93260fSMatthew G. Knepley PetscBool binary, useregions = PETSC_FALSE, markvertices = PETSC_FALSE, multipleTags = PETSC_FALSE; 14850598e1a2SLisandro Dalcin PetscBool hybrid = interpolate, periodic = PETSC_TRUE; 1486066ea43fSLisandro Dalcin PetscBool highOrder = PETSC_TRUE, highOrderSet, project = PETSC_FALSE; 1487066ea43fSLisandro Dalcin PetscBool isSimplex = PETSC_FALSE, isHybrid = PETSC_FALSE, hasTetra = PETSC_FALSE; 14880598e1a2SLisandro Dalcin PetscMPIInt rank; 1489331830f3SMatthew G. Knepley 1490331830f3SMatthew G. Knepley PetscFunctionBegin; 14919566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1492d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)viewer); 1493d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Gmsh options"); 1494df93260fSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_gmsh_hybrid", "Force triangular prisms to use tensor order", "DMPlexCreateGmsh", hybrid, &hybrid, NULL)); 14959566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_periodic", "Read Gmsh periodic section", "DMPlexCreateGmsh", periodic, &periodic, NULL)); 14969566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_highorder", "Generate high-order coordinates", "DMPlexCreateGmsh", highOrder, &highOrder, &highOrderSet)); 14979566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_project", "Project high-order coordinates to a different space", "DMPlexCreateGmsh", project, &project, NULL)); 14989566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_use_regions", "Generate labels with region names", "DMPlexCreateGmsh", useregions, &useregions, NULL)); 14999566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_mark_vertices", "Add vertices to generated labels", "DMPlexCreateGmsh", markvertices, &markvertices, NULL)); 1500df93260fSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_gmsh_multiple_tags", "Allow multiple tags for default labels", "DMPlexCreateGmsh", multipleTags, &multipleTags, NULL)); 15019566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_gmsh_spacedim", "Embedding space dimension", "DMPlexCreateGmsh", coordDim, &coordDim, NULL, PETSC_DECIDE)); 15029db5b827SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_localize_height", "Localize edges and faces in addition to cells", "", maxHeight, &maxHeight, NULL, 0)); 1503d0609cedSBarry Smith PetscOptionsHeadEnd(); 1504d0609cedSBarry Smith PetscOptionsEnd(); 15050598e1a2SLisandro Dalcin 15069566063dSJacob Faibussowitsch PetscCall(GmshCellInfoSetUp()); 150711c56cb0SLisandro Dalcin 15089566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 15099566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 15109566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CreateGmsh, *dm, NULL, NULL, NULL)); 151111c56cb0SLisandro Dalcin 15129566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &binary)); 151311c56cb0SLisandro Dalcin 151411c56cb0SLisandro Dalcin /* Binary viewers read on all ranks, get subviewer to read only in rank 0 */ 15153b46f529SLisandro Dalcin if (binary) { 151611c56cb0SLisandro Dalcin parentviewer = viewer; 15179566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(parentviewer, PETSC_COMM_SELF, &viewer)); 151811c56cb0SLisandro Dalcin } 151911c56cb0SLisandro Dalcin 1520dd400576SPatrick Sanan if (rank == 0) { 15210598e1a2SLisandro Dalcin GmshFile gmsh[1]; 1522698a79b9SLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 1523698a79b9SLisandro Dalcin PetscBool match; 1524331830f3SMatthew G. Knepley 15259566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(gmsh, 1)); 1526698a79b9SLisandro Dalcin gmsh->viewer = viewer; 1527698a79b9SLisandro Dalcin gmsh->binary = binary; 1528698a79b9SLisandro Dalcin 15299566063dSJacob Faibussowitsch PetscCall(GmshMeshCreate(&mesh)); 15300598e1a2SLisandro Dalcin 1531698a79b9SLisandro Dalcin /* Read mesh format */ 15329566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 15339566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$MeshFormat", line)); 15349566063dSJacob Faibussowitsch PetscCall(GmshReadMeshFormat(gmsh)); 15359566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndMeshFormat", line)); 153611c56cb0SLisandro Dalcin 1537dc0ede3bSMatthew G. Knepley /* OPTIONAL Read physical names */ 15389566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 15399566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, "$PhysicalNames", line, &match)); 1540dc0ede3bSMatthew G. Knepley if (match) { 15419566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$PhysicalNames", line)); 15429566063dSJacob Faibussowitsch PetscCall(GmshReadPhysicalNames(gmsh, mesh)); 15439566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndPhysicalNames", line)); 1544698a79b9SLisandro Dalcin /* Initial read for entity section */ 15459566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 1546dc0ede3bSMatthew G. Knepley } 154711c56cb0SLisandro Dalcin 1548de78e4feSLisandro Dalcin /* Read entities */ 1549698a79b9SLisandro Dalcin if (gmsh->fileFormat >= 40) { 15509566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$Entities", line)); 15519566063dSJacob Faibussowitsch PetscCall(GmshReadEntities(gmsh, mesh)); 15529566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndEntities", line)); 1553698a79b9SLisandro Dalcin /* Initial read for nodes section */ 15549566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 1555de78e4feSLisandro Dalcin } 1556de78e4feSLisandro Dalcin 1557698a79b9SLisandro Dalcin /* Read nodes */ 15589566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$Nodes", line)); 15599566063dSJacob Faibussowitsch PetscCall(GmshReadNodes(gmsh, mesh)); 15609566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndNodes", line)); 156111c56cb0SLisandro Dalcin 1562698a79b9SLisandro Dalcin /* Read elements */ 15639566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 15649566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$Elements", line)); 15659566063dSJacob Faibussowitsch PetscCall(GmshReadElements(gmsh, mesh)); 15669566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndElements", line)); 1567de78e4feSLisandro Dalcin 15680598e1a2SLisandro Dalcin /* Read periodic section (OPTIONAL) */ 1569698a79b9SLisandro Dalcin if (periodic) { 15709566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 15719566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, "$Periodic", line, &periodic)); 1572ef12879bSLisandro Dalcin } 1573ef12879bSLisandro Dalcin if (periodic) { 15749566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$Periodic", line)); 15759566063dSJacob Faibussowitsch PetscCall(GmshReadPeriodic(gmsh, mesh)); 15769566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndPeriodic", line)); 1577698a79b9SLisandro Dalcin } 1578698a79b9SLisandro Dalcin 15799566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->wbuf)); 15809566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->sbuf)); 15819566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->nbuf)); 15820598e1a2SLisandro Dalcin 15830598e1a2SLisandro Dalcin dim = mesh->dim; 1584066ea43fSLisandro Dalcin order = mesh->order; 15850598e1a2SLisandro Dalcin numNodes = mesh->numNodes; 15860598e1a2SLisandro Dalcin numElems = mesh->numElems; 15870598e1a2SLisandro Dalcin numVerts = mesh->numVerts; 15880598e1a2SLisandro Dalcin numCells = mesh->numCells; 1589066ea43fSLisandro Dalcin 1590066ea43fSLisandro Dalcin { 1591066ea43fSLisandro Dalcin GmshElement *elemA = mesh->numCells > 0 ? mesh->elements : NULL; 1592066ea43fSLisandro Dalcin GmshElement *elemB = elemA ? elemA + mesh->numCells - 1 : NULL; 1593066ea43fSLisandro Dalcin int ptA = elemA ? GmshCellMap[elemA->cellType].polytope : -1; 1594066ea43fSLisandro Dalcin int ptB = elemB ? GmshCellMap[elemB->cellType].polytope : -1; 1595066ea43fSLisandro Dalcin isSimplex = (ptA == GMSH_QUA || ptA == GMSH_HEX) ? PETSC_FALSE : PETSC_TRUE; 1596066ea43fSLisandro Dalcin isHybrid = (ptA == ptB) ? PETSC_FALSE : PETSC_TRUE; 1597066ea43fSLisandro Dalcin hasTetra = (ptA == GMSH_TET) ? PETSC_TRUE : PETSC_FALSE; 1598066ea43fSLisandro Dalcin } 1599698a79b9SLisandro Dalcin } 1600698a79b9SLisandro Dalcin 160148a46eb9SPierre Jolivet if (parentviewer) PetscCall(PetscViewerRestoreSubViewer(parentviewer, PETSC_COMM_SELF, &viewer)); 1602698a79b9SLisandro Dalcin 1603066ea43fSLisandro Dalcin { 1604066ea43fSLisandro Dalcin int buf[6]; 1605698a79b9SLisandro Dalcin 1606066ea43fSLisandro Dalcin buf[0] = (int)dim; 1607066ea43fSLisandro Dalcin buf[1] = (int)order; 1608066ea43fSLisandro Dalcin buf[2] = periodic; 1609066ea43fSLisandro Dalcin buf[3] = isSimplex; 1610066ea43fSLisandro Dalcin buf[4] = isHybrid; 1611066ea43fSLisandro Dalcin buf[5] = hasTetra; 1612066ea43fSLisandro Dalcin 16139566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(buf, 6, MPI_INT, 0, comm)); 1614066ea43fSLisandro Dalcin 1615066ea43fSLisandro Dalcin dim = buf[0]; 1616066ea43fSLisandro Dalcin order = buf[1]; 1617066ea43fSLisandro Dalcin periodic = buf[2] ? PETSC_TRUE : PETSC_FALSE; 1618066ea43fSLisandro Dalcin isSimplex = buf[3] ? PETSC_TRUE : PETSC_FALSE; 1619066ea43fSLisandro Dalcin isHybrid = buf[4] ? PETSC_TRUE : PETSC_FALSE; 1620066ea43fSLisandro Dalcin hasTetra = buf[5] ? PETSC_TRUE : PETSC_FALSE; 1621dea2a3c7SStefano Zampini } 1622dea2a3c7SStefano Zampini 1623066ea43fSLisandro Dalcin if (!highOrderSet) highOrder = (order > 1) ? PETSC_TRUE : PETSC_FALSE; 162408401ef6SPierre Jolivet PetscCheck(!highOrder || !isHybrid, comm, PETSC_ERR_SUP, "No support for discretization on hybrid meshes yet"); 1625066ea43fSLisandro Dalcin 16260598e1a2SLisandro Dalcin /* We do not want this label automatically computed, instead we fill it here */ 16279566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "celltype")); 162811c56cb0SLisandro Dalcin 1629a4bb7517SMichael Lange /* Allocate the cell-vertex mesh */ 16309566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(*dm, 0, numCells + numVerts)); 16310598e1a2SLisandro Dalcin for (cell = 0; cell < numCells; ++cell) { 16320598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + cell; 16330598e1a2SLisandro Dalcin DMPolytopeType ctype = DMPolytopeTypeFromGmsh(elem->cellType); 16340598e1a2SLisandro Dalcin if (hybrid && hasTetra && ctype == DM_POLYTOPE_TRI_PRISM) ctype = DM_POLYTOPE_TRI_PRISM_TENSOR; 16359566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(*dm, cell, elem->numVerts)); 16369566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(*dm, cell, ctype)); 1637db397164SMichael Lange } 163848a46eb9SPierre Jolivet for (v = numCells; v < numCells + numVerts; ++v) PetscCall(DMPlexSetCellType(*dm, v, DM_POLYTOPE_POINT)); 16399566063dSJacob Faibussowitsch PetscCall(DMSetUp(*dm)); 164096ca5757SLisandro Dalcin 1641a4bb7517SMichael Lange /* Add cell-vertex connections */ 16420598e1a2SLisandro Dalcin for (cell = 0; cell < numCells; ++cell) { 16430598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + cell; 16440598e1a2SLisandro Dalcin for (v = 0; v < elem->numVerts; ++v) { 16450598e1a2SLisandro Dalcin const PetscInt nn = elem->nodes[v]; 16460598e1a2SLisandro Dalcin const PetscInt vv = mesh->vertexMap[nn]; 16470598e1a2SLisandro Dalcin cone[v] = numCells + vv; 1648db397164SMichael Lange } 16499566063dSJacob Faibussowitsch PetscCall(DMPlexReorderCell(*dm, cell, cone)); 16509566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(*dm, cell, cone)); 1651a4bb7517SMichael Lange } 165296ca5757SLisandro Dalcin 16539566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 16549566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(*dm)); 16559566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(*dm)); 1656331830f3SMatthew G. Knepley if (interpolate) { 16575fd9971aSMatthew G. Knepley DM idm; 1658331830f3SMatthew G. Knepley 16599566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 16609566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 1661331830f3SMatthew G. Knepley *dm = idm; 1662331830f3SMatthew G. Knepley } 16639db5b827SMatthew G. Knepley PetscCall(DMPlexGetDepthStratum(*dm, 0, &vStart, &vEnd)); 1664917266a4SLisandro Dalcin 1665dd400576SPatrick Sanan if (rank == 0) { 1666a45dabc8SMatthew G. Knepley const PetscInt Nr = useregions ? mesh->numRegions : 0; 1667d1a54cefSMatthew G. Knepley 16689566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(Nr, ®ionSets)); 16690598e1a2SLisandro Dalcin for (cell = 0, e = 0; e < numElems; ++e) { 16700598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + e; 16716e1dd89aSLawrence Mitchell 16726e1dd89aSLawrence Mitchell /* Create cell sets */ 16730598e1a2SLisandro Dalcin if (elem->dim == dim && dim > 0) { 16740598e1a2SLisandro Dalcin if (elem->numTags > 0) { 1675df93260fSMatthew G. Knepley PetscInt Nt = elem->numTags, t, r; 1676a45dabc8SMatthew G. Knepley 1677df93260fSMatthew G. Knepley for (t = 0; t < Nt; ++t) { 1678df93260fSMatthew G. Knepley const PetscInt tag = elem->tags[t]; 1679df93260fSMatthew G. Knepley const PetscBool generic = !Nr && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE; 1680df93260fSMatthew G. Knepley 1681df93260fSMatthew G. Knepley if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &cellSets, "Cell Sets", cell, tag)); 1682a45dabc8SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 1683df93260fSMatthew G. Knepley if (mesh->regionDims[r] != dim) continue; 16849566063dSJacob Faibussowitsch if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], cell, tag)); 1685a45dabc8SMatthew G. Knepley } 16866e1dd89aSLawrence Mitchell } 1687df93260fSMatthew G. Knepley } 1688917266a4SLisandro Dalcin cell++; 16896e1dd89aSLawrence Mitchell } 16900c070f12SSander Arens 16910598e1a2SLisandro Dalcin /* Create face sets */ 16920598e1a2SLisandro Dalcin if (interpolate && elem->dim == dim - 1) { 16930598e1a2SLisandro Dalcin PetscInt joinSize; 16940598e1a2SLisandro Dalcin const PetscInt *join = NULL; 16955ad74b4fSMatthew G. Knepley PetscInt Nt = elem->numTags, t, r; 1696a45dabc8SMatthew G. Knepley 16970598e1a2SLisandro Dalcin /* Find the relevant facet with vertex joins */ 16980598e1a2SLisandro Dalcin for (v = 0; v < elem->numVerts; ++v) { 16990598e1a2SLisandro Dalcin const PetscInt nn = elem->nodes[v]; 17000598e1a2SLisandro Dalcin const PetscInt vv = mesh->vertexMap[nn]; 17010598e1a2SLisandro Dalcin cone[v] = vStart + vv; 17020598e1a2SLisandro Dalcin } 17039566063dSJacob Faibussowitsch PetscCall(DMPlexGetFullJoin(*dm, elem->numVerts, cone, &joinSize, &join)); 170463a3b9bcSJacob 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); 17055ad74b4fSMatthew G. Knepley for (t = 0; t < Nt; ++t) { 17065ad74b4fSMatthew G. Knepley const PetscInt tag = elem->tags[t]; 1707df93260fSMatthew G. Knepley const PetscBool generic = !Nr && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE; 17085ad74b4fSMatthew G. Knepley 1709df93260fSMatthew G. Knepley if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &faceSets, "Face Sets", join[0], tag)); 1710a45dabc8SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 1711df93260fSMatthew G. Knepley if (mesh->regionDims[r] != dim - 1) continue; 17129566063dSJacob Faibussowitsch if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], join[0], tag)); 1713a45dabc8SMatthew G. Knepley } 17145ad74b4fSMatthew G. Knepley } 17159566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(*dm, elem->numVerts, cone, &joinSize, &join)); 17160598e1a2SLisandro Dalcin } 17170598e1a2SLisandro Dalcin 17180c070f12SSander Arens /* Create vertex sets */ 1719df93260fSMatthew G. Knepley if (elem->dim == 0 && markvertices) { 17200598e1a2SLisandro Dalcin if (elem->numTags > 0) { 17210598e1a2SLisandro Dalcin const PetscInt nn = elem->nodes[0]; 17220598e1a2SLisandro Dalcin const PetscInt vv = mesh->vertexMap[nn]; 1723a45dabc8SMatthew G. Knepley const PetscInt tag = elem->tags[0]; 1724a45dabc8SMatthew G. Knepley PetscInt r; 1725a45dabc8SMatthew G. Knepley 17269566063dSJacob Faibussowitsch if (!Nr) PetscCall(DMSetLabelValue_Fast(*dm, &vertSets, "Vertex Sets", vStart + vv, tag)); 172781a1af93SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 1728df93260fSMatthew G. Knepley if (mesh->regionDims[r] != 0) continue; 17299566063dSJacob Faibussowitsch if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], vStart + vv, tag)); 173081a1af93SMatthew G. Knepley } 173181a1af93SMatthew G. Knepley } 173281a1af93SMatthew G. Knepley } 173381a1af93SMatthew G. Knepley } 173481a1af93SMatthew G. Knepley if (markvertices) { 173581a1af93SMatthew G. Knepley for (v = 0; v < numNodes; ++v) { 173681a1af93SMatthew G. Knepley const PetscInt vv = mesh->vertexMap[v]; 17377d5b9244SMatthew G. Knepley const PetscInt *tags = &mesh->nodelist->tag[v * GMSH_MAX_TAGS]; 17387d5b9244SMatthew G. Knepley PetscInt r, t; 173981a1af93SMatthew G. Knepley 17407d5b9244SMatthew G. Knepley for (t = 0; t < GMSH_MAX_TAGS; ++t) { 17417d5b9244SMatthew G. Knepley const PetscInt tag = tags[t]; 1742df93260fSMatthew G. Knepley const PetscBool generic = !Nr && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE; 17437d5b9244SMatthew G. Knepley 17447d5b9244SMatthew G. Knepley if (tag == -1) continue; 1745df93260fSMatthew G. Knepley if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &vertSets, "Vertex Sets", vStart + vv, tag)); 1746a45dabc8SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 17479566063dSJacob Faibussowitsch if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], vStart + vv, tag)); 17480598e1a2SLisandro Dalcin } 17490598e1a2SLisandro Dalcin } 17500598e1a2SLisandro Dalcin } 17510598e1a2SLisandro Dalcin } 17529566063dSJacob Faibussowitsch PetscCall(PetscFree(regionSets)); 1753a45dabc8SMatthew G. Knepley } 17540598e1a2SLisandro Dalcin 17557dd454faSLisandro Dalcin { /* Create Cell/Face/Vertex Sets labels at all processes */ 17569371c9d4SSatish Balay enum { 17579371c9d4SSatish Balay n = 4 17589371c9d4SSatish Balay }; 17597dd454faSLisandro Dalcin PetscBool flag[n]; 17607dd454faSLisandro Dalcin 17617dd454faSLisandro Dalcin flag[0] = cellSets ? PETSC_TRUE : PETSC_FALSE; 17627dd454faSLisandro Dalcin flag[1] = faceSets ? PETSC_TRUE : PETSC_FALSE; 17637dd454faSLisandro Dalcin flag[2] = vertSets ? PETSC_TRUE : PETSC_FALSE; 17647dd454faSLisandro Dalcin flag[3] = marker ? PETSC_TRUE : PETSC_FALSE; 17659566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(flag, n, MPIU_BOOL, 0, comm)); 17669566063dSJacob Faibussowitsch if (flag[0]) PetscCall(DMCreateLabel(*dm, "Cell Sets")); 17679566063dSJacob Faibussowitsch if (flag[1]) PetscCall(DMCreateLabel(*dm, "Face Sets")); 17689566063dSJacob Faibussowitsch if (flag[2]) PetscCall(DMCreateLabel(*dm, "Vertex Sets")); 17699566063dSJacob Faibussowitsch if (flag[3]) PetscCall(DMCreateLabel(*dm, "marker")); 17707dd454faSLisandro Dalcin } 17717dd454faSLisandro Dalcin 17720598e1a2SLisandro Dalcin if (periodic) { 17739566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(numVerts, &periodicVerts)); 17740598e1a2SLisandro Dalcin for (n = 0; n < numNodes; ++n) { 17750598e1a2SLisandro Dalcin if (mesh->vertexMap[n] >= 0) { 17760598e1a2SLisandro Dalcin if (PetscUnlikely(mesh->periodMap[n] != n)) { 17770598e1a2SLisandro Dalcin PetscInt m = mesh->periodMap[n]; 17789566063dSJacob Faibussowitsch PetscCall(PetscBTSet(periodicVerts, mesh->vertexMap[n])); 17799566063dSJacob Faibussowitsch PetscCall(PetscBTSet(periodicVerts, mesh->vertexMap[m])); 17800598e1a2SLisandro Dalcin } 17810598e1a2SLisandro Dalcin } 17820598e1a2SLisandro Dalcin } 17839db5b827SMatthew G. Knepley PetscCall(DMGetCoordinateDM(*dm, &cdm)); 1784eae3dc7dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxHeight + 1, &periodicCells)); 17859db5b827SMatthew G. Knepley for (PetscInt h = 0; h <= maxHeight; ++h) { 17869db5b827SMatthew G. Knepley PetscInt pStart, pEnd; 17879db5b827SMatthew G. Knepley 17889db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(*dm, h, &pStart, &pEnd)); 17899db5b827SMatthew G. Knepley PetscCall(PetscBTCreate(pEnd - pStart, &periodicCells[h])); 17909db5b827SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 17919db5b827SMatthew G. Knepley PetscInt *closure = NULL; 17929db5b827SMatthew G. Knepley PetscInt Ncl; 17939db5b827SMatthew G. Knepley 17949db5b827SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure)); 17959db5b827SMatthew G. Knepley for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) { 17969db5b827SMatthew G. Knepley if (closure[cl] >= vStart && closure[cl] < vEnd) { 17979db5b827SMatthew G. Knepley if (PetscUnlikely(PetscBTLookup(periodicVerts, closure[cl] - vStart))) { 17989db5b827SMatthew G. Knepley PetscCall(PetscBTSet(periodicCells[h], p - pStart)); 17999371c9d4SSatish Balay break; 18000c070f12SSander Arens } 18010c070f12SSander Arens } 18020c070f12SSander Arens } 18039db5b827SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure)); 18049db5b827SMatthew G. Knepley } 18059db5b827SMatthew G. Knepley } 180616ad7e67SMichael Lange } 180716ad7e67SMichael Lange 1808066ea43fSLisandro Dalcin /* Setup coordinate DM */ 18090598e1a2SLisandro Dalcin if (coordDim < 0) coordDim = dim; 18109566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(*dm, coordDim)); 18119566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(*dm, &cdm)); 1812066ea43fSLisandro Dalcin if (highOrder) { 1813066ea43fSLisandro Dalcin PetscFE fe; 1814066ea43fSLisandro Dalcin PetscBool continuity = periodic ? PETSC_FALSE : PETSC_TRUE; 1815066ea43fSLisandro Dalcin PetscDTNodeType nodeType = PETSCDTNODES_EQUISPACED; 1816066ea43fSLisandro Dalcin 1817066ea43fSLisandro Dalcin if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */ 1818066ea43fSLisandro Dalcin 18199566063dSJacob Faibussowitsch PetscCall(GmshCreateFE(comm, NULL, isSimplex, continuity, nodeType, dim, coordDim, order, &fe)); 18209566063dSJacob Faibussowitsch PetscCall(PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_fe_view")); 18219566063dSJacob Faibussowitsch PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)fe)); 18229566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 18239566063dSJacob Faibussowitsch PetscCall(DMCreateDS(cdm)); 1824066ea43fSLisandro Dalcin } 18256858538eSMatthew G. Knepley if (periodic) { 18266858538eSMatthew G. Knepley PetscCall(DMClone(cdm, &cdmCell)); 18276858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(*dm, cdmCell)); 18286858538eSMatthew G. Knepley } 1829066ea43fSLisandro Dalcin 1830066ea43fSLisandro Dalcin /* Create coordinates */ 1831066ea43fSLisandro Dalcin if (highOrder) { 1832066ea43fSLisandro Dalcin PetscInt maxDof = GmshNumNodes_HEX(order) * coordDim; 1833066ea43fSLisandro Dalcin double *coords = mesh ? mesh->nodelist->xyz : NULL; 1834066ea43fSLisandro Dalcin PetscSection section; 1835066ea43fSLisandro Dalcin PetscScalar *cellCoords; 1836066ea43fSLisandro Dalcin 18379566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(cdm, NULL)); 18386858538eSMatthew G. Knepley PetscCall(DMGetLocalSection(cdm, &cs)); 18396858538eSMatthew G. Knepley PetscCall(PetscSectionClone(cs, §ion)); 18409566063dSJacob Faibussowitsch PetscCall(DMPlexSetClosurePermutationTensor(cdm, 0, section)); /* XXX Implement DMPlexSetClosurePermutationLexicographic() */ 1841066ea43fSLisandro Dalcin 18429566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(cdm, &coordinates)); 18439566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof, &cellCoords)); 1844066ea43fSLisandro Dalcin for (cell = 0; cell < numCells; ++cell) { 1845066ea43fSLisandro Dalcin GmshElement *elem = mesh->elements + cell; 1846066ea43fSLisandro Dalcin const int *lexorder = GmshCellMap[elem->cellType].lexorder(); 1847b9bf55e5SMatthew G. Knepley int s = 0; 1848066ea43fSLisandro Dalcin for (n = 0; n < elem->numNodes; ++n) { 1849b9bf55e5SMatthew G. Knepley while (lexorder[n + s] < 0) ++s; 1850b9bf55e5SMatthew G. Knepley const PetscInt node = elem->nodes[lexorder[n + s]]; 1851b9bf55e5SMatthew G. Knepley for (d = 0; d < coordDim; ++d) cellCoords[(n + s) * coordDim + d] = (PetscReal)coords[node * 3 + d]; 1852b9bf55e5SMatthew G. Knepley } 1853b9bf55e5SMatthew G. Knepley if (s) { 1854b9bf55e5SMatthew G. Knepley /* For the coordinate mapping we weight vertices by -1/4 and edges by 1/2, which we get from Q_2 interpolation */ 1855b9bf55e5SMatthew G. Knepley PetscReal quaCenterWeights[9] = {-0.25, 0.5, -0.25, 0.5, 0.0, 0.5, -0.25, 0.5, -0.25}; 1856b9bf55e5SMatthew G. Knepley /* For the coordinate mapping we weight vertices by -1/4 and edges by 1/2, which we get from Q_2 interpolation */ 18579371c9d4SSatish 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}; 18589371c9d4SSatish 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}; 18599371c9d4SSatish 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}; 18609371c9d4SSatish 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}; 18619371c9d4SSatish 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}; 18629371c9d4SSatish 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}; 18639371c9d4SSatish 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}; 1864b9bf55e5SMatthew G. Knepley PetscReal *sdWeights2[9] = {NULL, NULL, NULL, NULL, quaCenterWeights, NULL, NULL, NULL, NULL}; 18659371c9d4SSatish Balay PetscReal *sdWeights3[27] = {NULL, NULL, NULL, NULL, hexBottomWeights, NULL, NULL, NULL, NULL, NULL, hexFrontWeights, NULL, hexLeftWeights, hexCenterWeights, hexRightWeights, NULL, hexBackWeights, NULL, 1866b9bf55e5SMatthew G. Knepley NULL, NULL, NULL, NULL, hexTopWeights, NULL, NULL, NULL, NULL}; 1867b9bf55e5SMatthew G. Knepley PetscReal **sdWeights[4] = {NULL, NULL, sdWeights2, sdWeights3}; 1868b9bf55e5SMatthew G. Knepley 1869b9bf55e5SMatthew G. Knepley /* Missing entries in serendipity cell, only works for 8-node quad and 20-node hex */ 1870b9bf55e5SMatthew G. Knepley for (n = 0; n < elem->numNodes + s; ++n) { 1871b9bf55e5SMatthew G. Knepley if (lexorder[n] >= 0) continue; 1872b9bf55e5SMatthew G. Knepley for (d = 0; d < coordDim; ++d) cellCoords[n * coordDim + d] = 0.0; 1873b9bf55e5SMatthew G. Knepley for (int bn = 0; bn < elem->numNodes + s; ++bn) { 1874b9bf55e5SMatthew G. Knepley if (lexorder[bn] < 0) continue; 1875b9bf55e5SMatthew G. Knepley const PetscReal *weights = sdWeights[coordDim][n]; 1876b9bf55e5SMatthew G. Knepley const PetscInt bnode = elem->nodes[lexorder[bn]]; 1877b9bf55e5SMatthew G. Knepley for (d = 0; d < coordDim; ++d) cellCoords[n * coordDim + d] += weights[bn] * (PetscReal)coords[bnode * 3 + d]; 1878b9bf55e5SMatthew G. Knepley } 1879b9bf55e5SMatthew G. Knepley } 1880066ea43fSLisandro Dalcin } 18819566063dSJacob Faibussowitsch PetscCall(DMPlexVecSetClosure(cdm, section, coordinates, cell, cellCoords, INSERT_VALUES)); 1882066ea43fSLisandro Dalcin } 18839566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 18849566063dSJacob Faibussowitsch PetscCall(PetscFree(cellCoords)); 1885066ea43fSLisandro Dalcin } else { 1886066ea43fSLisandro Dalcin PetscInt *nodeMap; 1887066ea43fSLisandro Dalcin double *coords = mesh ? mesh->nodelist->xyz : NULL; 1888066ea43fSLisandro Dalcin PetscScalar *pointCoords; 1889066ea43fSLisandro Dalcin 18906858538eSMatthew G. Knepley PetscCall(DMGetCoordinateSection(*dm, &cs)); 18916858538eSMatthew G. Knepley PetscCall(PetscSectionSetNumFields(cs, 1)); 18926858538eSMatthew G. Knepley PetscCall(PetscSectionSetFieldComponents(cs, 0, coordDim)); 18936858538eSMatthew G. Knepley PetscCall(PetscSectionSetChart(cs, numCells, numCells + numVerts)); 18946858538eSMatthew G. Knepley for (v = numCells; v < numCells + numVerts; ++v) { 18956858538eSMatthew G. Knepley PetscCall(PetscSectionSetDof(cs, v, coordDim)); 18966858538eSMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(cs, v, 0, coordDim)); 1897f45c9589SStefano Zampini } 18986858538eSMatthew G. Knepley PetscCall(PetscSectionSetUp(cs)); 18996858538eSMatthew G. Knepley 19006858538eSMatthew G. Knepley /* We need to localize coordinates on cells */ 19010598e1a2SLisandro Dalcin if (periodic) { 19029db5b827SMatthew G. Knepley PetscInt newStart = PETSC_MAX_INT, newEnd = -1, pStart, pEnd; 19039db5b827SMatthew G. Knepley 19046858538eSMatthew G. Knepley PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)cdmCell), &csCell)); 19056858538eSMatthew G. Knepley PetscCall(PetscSectionSetNumFields(csCell, 1)); 19066858538eSMatthew G. Knepley PetscCall(PetscSectionSetFieldComponents(csCell, 0, coordDim)); 19079db5b827SMatthew G. Knepley for (PetscInt h = 0; h <= maxHeight; h++) { 19089db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(cdmCell, h, &pStart, &pEnd)); 19099db5b827SMatthew G. Knepley newStart = PetscMin(newStart, pStart); 19109db5b827SMatthew G. Knepley newEnd = PetscMax(newEnd, pEnd); 19119db5b827SMatthew G. Knepley } 19129db5b827SMatthew G. Knepley PetscCall(PetscSectionSetChart(csCell, newStart, newEnd)); 19139db5b827SMatthew G. Knepley for (PetscInt h = 0; h <= maxHeight; h++) { 19149db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(cdmCell, h, &pStart, &pEnd)); 19159db5b827SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 19169db5b827SMatthew G. Knepley PetscInt *closure = NULL; 19179db5b827SMatthew G. Knepley PetscInt Ncl, Nv = 0; 19186858538eSMatthew G. Knepley 19199db5b827SMatthew G. Knepley if (PetscUnlikely(PetscBTLookup(periodicCells[h], p - pStart))) { 19209db5b827SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure)); 19219db5b827SMatthew G. Knepley for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) { 19229db5b827SMatthew G. Knepley if (closure[cl] >= vStart && closure[cl] < vEnd) ++Nv; 19239db5b827SMatthew G. Knepley } 19249db5b827SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure)); 19259db5b827SMatthew G. Knepley PetscCall(PetscSectionSetDof(csCell, p, Nv * coordDim)); 19269db5b827SMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(csCell, p, 0, Nv * coordDim)); 19279db5b827SMatthew G. Knepley } 1928f45c9589SStefano Zampini } 1929f45c9589SStefano Zampini } 19306858538eSMatthew G. Knepley PetscCall(PetscSectionSetUp(csCell)); 19316858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateSection(*dm, PETSC_DETERMINE, csCell)); 1932f45c9589SStefano Zampini } 1933066ea43fSLisandro Dalcin 19349566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(cdm, &coordinates)); 19359566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &pointCoords)); 19366858538eSMatthew G. Knepley PetscCall(PetscMalloc1(numVerts, &nodeMap)); 19376858538eSMatthew G. Knepley for (n = 0; n < numNodes; n++) 19386858538eSMatthew G. Knepley if (mesh->vertexMap[n] >= 0) nodeMap[mesh->vertexMap[n]] = n; 19396858538eSMatthew G. Knepley for (v = 0; v < numVerts; ++v) { 19406858538eSMatthew G. Knepley PetscInt off, node = nodeMap[v]; 19416858538eSMatthew G. Knepley 19426858538eSMatthew G. Knepley PetscCall(PetscSectionGetOffset(cs, numCells + v, &off)); 19436858538eSMatthew G. Knepley for (d = 0; d < coordDim; ++d) pointCoords[off + d] = (PetscReal)coords[node * 3 + d]; 19446858538eSMatthew G. Knepley } 19456858538eSMatthew G. Knepley PetscCall(VecRestoreArray(coordinates, &pointCoords)); 19466858538eSMatthew G. Knepley 19470598e1a2SLisandro Dalcin if (periodic) { 19489db5b827SMatthew G. Knepley PetscInt cStart, cEnd; 19499db5b827SMatthew G. Knepley 19509db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(cdmCell, 0, &cStart, &cEnd)); 19516858538eSMatthew G. Knepley PetscCall(DMCreateLocalVector(cdmCell, &coordinatesCell)); 19526858538eSMatthew G. Knepley PetscCall(VecGetArray(coordinatesCell, &pointCoords)); 19539db5b827SMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) { 19549db5b827SMatthew G. Knepley GmshElement *elem = mesh->elements + c - cStart; 19559db5b827SMatthew G. Knepley PetscInt *closure = NULL; 19569db5b827SMatthew G. Knepley PetscInt verts[8]; 19579db5b827SMatthew G. Knepley PetscInt Ncl, Nv = 0; 19589db5b827SMatthew G. Knepley 19599db5b827SMatthew G. Knepley for (PetscInt v = 0; v < elem->numVerts; ++v) cone[v] = elem->nodes[v]; 19609db5b827SMatthew G. Knepley PetscCall(DMPlexReorderCell(cdmCell, c, cone)); 19619db5b827SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(cdmCell, c, PETSC_TRUE, &Ncl, &closure)); 19629db5b827SMatthew G. Knepley for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) { 19639db5b827SMatthew G. Knepley if (closure[cl] >= vStart && closure[cl] < vEnd) verts[Nv++] = closure[cl]; 1964331830f3SMatthew G. Knepley } 19659db5b827SMatthew 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); 19669db5b827SMatthew G. Knepley for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) { 19679db5b827SMatthew G. Knepley const PetscInt point = closure[cl]; 19689db5b827SMatthew G. Knepley PetscInt hStart, h; 19699db5b827SMatthew G. Knepley 19709db5b827SMatthew G. Knepley PetscCall(DMPlexGetPointHeight(cdmCell, point, &h)); 19719db5b827SMatthew G. Knepley if (h > maxHeight) continue; 19729db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(cdmCell, h, &hStart, NULL)); 19739db5b827SMatthew G. Knepley if (PetscUnlikely(PetscBTLookup(periodicCells[h], point - hStart))) { 19749db5b827SMatthew G. Knepley PetscInt *pclosure = NULL; 19759db5b827SMatthew G. Knepley PetscInt Npcl, off, v; 19769db5b827SMatthew G. Knepley 19779db5b827SMatthew G. Knepley PetscCall(PetscSectionGetOffset(csCell, point, &off)); 19789db5b827SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(cdmCell, point, PETSC_TRUE, &Npcl, &pclosure)); 19799db5b827SMatthew G. Knepley for (PetscInt pcl = 0; pcl < Npcl * 2; pcl += 2) { 19809db5b827SMatthew G. Knepley if (pclosure[pcl] >= vStart && pclosure[pcl] < vEnd) { 19819db5b827SMatthew G. Knepley for (v = 0; v < Nv; ++v) 19829db5b827SMatthew G. Knepley if (verts[v] == pclosure[pcl]) break; 19839db5b827SMatthew 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); 19849db5b827SMatthew G. Knepley for (PetscInt d = 0; d < coordDim; ++d) pointCoords[off++] = (PetscReal)coords[cone[v] * 3 + d]; 19859db5b827SMatthew G. Knepley ++v; 19869db5b827SMatthew G. Knepley } 19879db5b827SMatthew G. Knepley } 19889db5b827SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(cdmCell, point, PETSC_TRUE, &Npcl, &pclosure)); 19899db5b827SMatthew G. Knepley } 19909db5b827SMatthew G. Knepley } 19919db5b827SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(cdmCell, c, PETSC_TRUE, &Ncl, &closure)); 1992331830f3SMatthew G. Knepley } 19936858538eSMatthew G. Knepley PetscCall(VecSetBlockSize(coordinatesCell, coordDim)); 19946858538eSMatthew G. Knepley PetscCall(VecRestoreArray(coordinatesCell, &pointCoords)); 19956858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(*dm, coordinatesCell)); 19966858538eSMatthew G. Knepley PetscCall(VecDestroy(&coordinatesCell)); 1997331830f3SMatthew G. Knepley } 19989db5b827SMatthew G. Knepley PetscCall(PetscFree(nodeMap)); 19996858538eSMatthew G. Knepley PetscCall(PetscSectionDestroy(&csCell)); 20006858538eSMatthew G. Knepley PetscCall(DMDestroy(&cdmCell)); 2001066ea43fSLisandro Dalcin } 2002066ea43fSLisandro Dalcin 20039566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 20049566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, coordDim)); 20059566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(*dm, coordinates)); 20069566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 200711c56cb0SLisandro Dalcin 20089566063dSJacob Faibussowitsch PetscCall(GmshMeshDestroy(&mesh)); 20099566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&periodicVerts)); 2010eae3dc7dSJacob Faibussowitsch if (periodic) { 2011eae3dc7dSJacob Faibussowitsch for (PetscInt h = 0; h <= maxHeight; ++h) PetscCall(PetscBTDestroy(periodicCells + h)); 2012eae3dc7dSJacob Faibussowitsch PetscCall(PetscFree(periodicCells)); 2013eae3dc7dSJacob Faibussowitsch } 201411c56cb0SLisandro Dalcin 2015066ea43fSLisandro Dalcin if (highOrder && project) { 2016066ea43fSLisandro Dalcin PetscFE fe; 2017066ea43fSLisandro Dalcin const char prefix[] = "dm_plex_gmsh_project_"; 2018066ea43fSLisandro Dalcin PetscBool continuity = periodic ? PETSC_FALSE : PETSC_TRUE; 2019066ea43fSLisandro Dalcin PetscDTNodeType nodeType = PETSCDTNODES_GAUSSJACOBI; 2020066ea43fSLisandro Dalcin 2021066ea43fSLisandro Dalcin if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */ 20229566063dSJacob Faibussowitsch PetscCall(GmshCreateFE(comm, prefix, isSimplex, continuity, nodeType, dim, coordDim, order, &fe)); 20239566063dSJacob Faibussowitsch PetscCall(PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_project_fe_view")); 20249566063dSJacob Faibussowitsch PetscCall(DMProjectCoordinates(*dm, fe)); 20259566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 2026066ea43fSLisandro Dalcin } 2027066ea43fSLisandro Dalcin 20289566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CreateGmsh, *dm, NULL, NULL, NULL)); 20293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2030331830f3SMatthew G. Knepley } 2031