1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/
2730356f6SLisandro Dalcin #include <petsc/private/hashmapi.h>
3331830f3SMatthew G. Knepley
4066ea43fSLisandro Dalcin #include <../src/dm/impls/plex/gmshlex.h>
5066ea43fSLisandro Dalcin
6066ea43fSLisandro Dalcin #define GMSH_LEXORDER_ITEM(T, p) \
7d71ae5a4SJacob Faibussowitsch static int *GmshLexOrder_##T##_##p(void) \
8d71ae5a4SJacob Faibussowitsch { \
9066ea43fSLisandro Dalcin static int Gmsh_LexOrder_##T##_##p[GmshNumNodes_##T(p)] = {-1}; \
10066ea43fSLisandro Dalcin int *lex = Gmsh_LexOrder_##T##_##p; \
11066ea43fSLisandro Dalcin if (lex[0] == -1) (void)GmshLexOrder_##T(p, lex, 0); \
12066ea43fSLisandro Dalcin return lex; \
13066ea43fSLisandro Dalcin }
14066ea43fSLisandro Dalcin
GmshLexOrder_QUA_2_Serendipity(void)15d71ae5a4SJacob Faibussowitsch static int *GmshLexOrder_QUA_2_Serendipity(void)
16d71ae5a4SJacob Faibussowitsch {
17b9bf55e5SMatthew G. Knepley static int Gmsh_LexOrder_QUA_2_Serendipity[9] = {-1};
18b9bf55e5SMatthew G. Knepley int *lex = Gmsh_LexOrder_QUA_2_Serendipity;
19b9bf55e5SMatthew G. Knepley if (lex[0] == -1) {
20b9bf55e5SMatthew G. Knepley /* Vertices */
219371c9d4SSatish Balay lex[0] = 0;
229371c9d4SSatish Balay lex[2] = 1;
239371c9d4SSatish Balay lex[8] = 2;
249371c9d4SSatish Balay lex[6] = 3;
25b9bf55e5SMatthew G. Knepley /* Edges */
269371c9d4SSatish Balay lex[1] = 4;
279371c9d4SSatish Balay lex[5] = 5;
289371c9d4SSatish Balay lex[7] = 6;
299371c9d4SSatish Balay lex[3] = 7;
30b9bf55e5SMatthew G. Knepley /* Cell */
31b9bf55e5SMatthew G. Knepley lex[4] = -8;
32b9bf55e5SMatthew G. Knepley }
33b9bf55e5SMatthew G. Knepley return lex;
34b9bf55e5SMatthew G. Knepley }
35b9bf55e5SMatthew G. Knepley
GmshLexOrder_HEX_2_Serendipity(void)36d71ae5a4SJacob Faibussowitsch static int *GmshLexOrder_HEX_2_Serendipity(void)
37d71ae5a4SJacob Faibussowitsch {
38b9bf55e5SMatthew G. Knepley static int Gmsh_LexOrder_HEX_2_Serendipity[27] = {-1};
39b9bf55e5SMatthew G. Knepley int *lex = Gmsh_LexOrder_HEX_2_Serendipity;
40b9bf55e5SMatthew G. Knepley if (lex[0] == -1) {
41b9bf55e5SMatthew G. Knepley /* Vertices */
429371c9d4SSatish Balay lex[0] = 0;
439371c9d4SSatish Balay lex[2] = 1;
449371c9d4SSatish Balay lex[8] = 2;
459371c9d4SSatish Balay lex[6] = 3;
469371c9d4SSatish Balay lex[18] = 4;
479371c9d4SSatish Balay lex[20] = 5;
489371c9d4SSatish Balay lex[26] = 6;
499371c9d4SSatish Balay lex[24] = 7;
50b9bf55e5SMatthew G. Knepley /* Edges */
519371c9d4SSatish Balay lex[1] = 8;
529371c9d4SSatish Balay lex[3] = 9;
539371c9d4SSatish Balay lex[9] = 10;
549371c9d4SSatish Balay lex[5] = 11;
559371c9d4SSatish Balay lex[11] = 12;
569371c9d4SSatish Balay lex[7] = 13;
579371c9d4SSatish Balay lex[17] = 14;
589371c9d4SSatish Balay lex[15] = 15;
599371c9d4SSatish Balay lex[19] = 16;
609371c9d4SSatish Balay lex[21] = 17;
619371c9d4SSatish Balay lex[23] = 18;
629371c9d4SSatish Balay lex[25] = 19;
63b9bf55e5SMatthew G. Knepley /* Faces */
649371c9d4SSatish Balay lex[4] = -20;
659371c9d4SSatish Balay lex[10] = -21;
669371c9d4SSatish Balay lex[12] = -22;
679371c9d4SSatish Balay lex[14] = -23;
689371c9d4SSatish Balay lex[16] = -24;
699371c9d4SSatish Balay lex[22] = -25;
70b9bf55e5SMatthew G. Knepley /* Cell */
71b9bf55e5SMatthew G. Knepley lex[13] = -26;
72b9bf55e5SMatthew G. Knepley }
73b9bf55e5SMatthew G. Knepley return lex;
74b9bf55e5SMatthew G. Knepley }
75b9bf55e5SMatthew G. Knepley
76066ea43fSLisandro Dalcin #define GMSH_LEXORDER_LIST(T) \
77066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 1) \
78066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 2) \
79066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 3) \
80066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 4) \
81066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 5) \
82066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 6) \
83066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 7) \
84066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 8) \
85066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 9) \
86066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 10)
87066ea43fSLisandro Dalcin
88066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(VTX, 0)
89066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(SEG)
90066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(TRI)
91066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(QUA)
92066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(TET)
93066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(HEX)
94066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(PRI)
95066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(PYR)
96066ea43fSLisandro Dalcin
97066ea43fSLisandro Dalcin typedef enum {
98066ea43fSLisandro Dalcin GMSH_VTX = 0,
99066ea43fSLisandro Dalcin GMSH_SEG = 1,
100066ea43fSLisandro Dalcin GMSH_TRI = 2,
101066ea43fSLisandro Dalcin GMSH_QUA = 3,
102066ea43fSLisandro Dalcin GMSH_TET = 4,
103066ea43fSLisandro Dalcin GMSH_HEX = 5,
104066ea43fSLisandro Dalcin GMSH_PRI = 6,
105066ea43fSLisandro Dalcin GMSH_PYR = 7,
106066ea43fSLisandro Dalcin GMSH_NUM_POLYTOPES = 8
107066ea43fSLisandro Dalcin } GmshPolytopeType;
108066ea43fSLisandro Dalcin
109de78e4feSLisandro Dalcin typedef struct {
1100598e1a2SLisandro Dalcin int cellType;
111066ea43fSLisandro Dalcin int polytope;
1120598e1a2SLisandro Dalcin int dim;
1130598e1a2SLisandro Dalcin int order;
114066ea43fSLisandro Dalcin int numVerts;
1150598e1a2SLisandro Dalcin int numNodes;
116066ea43fSLisandro Dalcin int *(*lexorder)(void);
1170598e1a2SLisandro Dalcin } GmshCellInfo;
1180598e1a2SLisandro Dalcin
11910dd146fSPierre Jolivet #define GmshCellEntry(cellType, polytope, dim, order) {cellType, GMSH_##polytope, dim, order, GmshNumNodes_##polytope(1), GmshNumNodes_##polytope(order), GmshLexOrder_##polytope##_##order}
1200598e1a2SLisandro Dalcin
1210598e1a2SLisandro Dalcin static const GmshCellInfo GmshCellTable[] = {
122066ea43fSLisandro Dalcin GmshCellEntry(15, VTX, 0, 0),
1230598e1a2SLisandro Dalcin
1249371c9d4SSatish Balay GmshCellEntry(1, SEG, 1, 1), GmshCellEntry(8, SEG, 1, 2), GmshCellEntry(26, SEG, 1, 3),
1259371c9d4SSatish Balay GmshCellEntry(27, SEG, 1, 4), GmshCellEntry(28, SEG, 1, 5), GmshCellEntry(62, SEG, 1, 6),
1269371c9d4SSatish Balay GmshCellEntry(63, SEG, 1, 7), GmshCellEntry(64, SEG, 1, 8), GmshCellEntry(65, SEG, 1, 9),
127066ea43fSLisandro Dalcin GmshCellEntry(66, SEG, 1, 10),
1280598e1a2SLisandro Dalcin
1299371c9d4SSatish Balay GmshCellEntry(2, TRI, 2, 1), GmshCellEntry(9, TRI, 2, 2), GmshCellEntry(21, TRI, 2, 3),
1309371c9d4SSatish Balay GmshCellEntry(23, TRI, 2, 4), GmshCellEntry(25, TRI, 2, 5), GmshCellEntry(42, TRI, 2, 6),
1319371c9d4SSatish Balay GmshCellEntry(43, TRI, 2, 7), GmshCellEntry(44, TRI, 2, 8), GmshCellEntry(45, TRI, 2, 9),
132066ea43fSLisandro Dalcin GmshCellEntry(46, TRI, 2, 10),
1330598e1a2SLisandro Dalcin
1349371c9d4SSatish Balay GmshCellEntry(3, QUA, 2, 1), GmshCellEntry(10, QUA, 2, 2), {16, GMSH_QUA, 2, 2, 4, 8, GmshLexOrder_QUA_2_Serendipity},
1359371c9d4SSatish Balay GmshCellEntry(36, QUA, 2, 3), GmshCellEntry(37, QUA, 2, 4), GmshCellEntry(38, QUA, 2, 5),
1369371c9d4SSatish Balay GmshCellEntry(47, QUA, 2, 6), GmshCellEntry(48, QUA, 2, 7), GmshCellEntry(49, QUA, 2, 8),
1379371c9d4SSatish Balay GmshCellEntry(50, QUA, 2, 9), GmshCellEntry(51, QUA, 2, 10),
1380598e1a2SLisandro Dalcin
1399371c9d4SSatish Balay GmshCellEntry(4, TET, 3, 1), GmshCellEntry(11, TET, 3, 2), GmshCellEntry(29, TET, 3, 3),
1409371c9d4SSatish Balay GmshCellEntry(30, TET, 3, 4), GmshCellEntry(31, TET, 3, 5), GmshCellEntry(71, TET, 3, 6),
1419371c9d4SSatish Balay GmshCellEntry(72, TET, 3, 7), GmshCellEntry(73, TET, 3, 8), GmshCellEntry(74, TET, 3, 9),
142066ea43fSLisandro Dalcin GmshCellEntry(75, TET, 3, 10),
1430598e1a2SLisandro Dalcin
1449371c9d4SSatish Balay GmshCellEntry(5, HEX, 3, 1), GmshCellEntry(12, HEX, 3, 2), {17, GMSH_HEX, 3, 2, 8, 20, GmshLexOrder_HEX_2_Serendipity},
1459371c9d4SSatish Balay GmshCellEntry(92, HEX, 3, 3), GmshCellEntry(93, HEX, 3, 4), GmshCellEntry(94, HEX, 3, 5),
1469371c9d4SSatish Balay GmshCellEntry(95, HEX, 3, 6), GmshCellEntry(96, HEX, 3, 7), GmshCellEntry(97, HEX, 3, 8),
1479371c9d4SSatish Balay GmshCellEntry(98, HEX, 3, 9), GmshCellEntry(-1, HEX, 3, 10),
1480598e1a2SLisandro Dalcin
1499371c9d4SSatish Balay GmshCellEntry(6, PRI, 3, 1), GmshCellEntry(13, PRI, 3, 2), GmshCellEntry(90, PRI, 3, 3),
1509371c9d4SSatish Balay GmshCellEntry(91, PRI, 3, 4), GmshCellEntry(106, PRI, 3, 5), GmshCellEntry(107, PRI, 3, 6),
1519371c9d4SSatish Balay GmshCellEntry(108, PRI, 3, 7), GmshCellEntry(109, PRI, 3, 8), GmshCellEntry(110, PRI, 3, 9),
152066ea43fSLisandro Dalcin GmshCellEntry(-1, PRI, 3, 10),
1530598e1a2SLisandro Dalcin
1549371c9d4SSatish Balay GmshCellEntry(7, PYR, 3, 1), GmshCellEntry(14, PYR, 3, 2), GmshCellEntry(118, PYR, 3, 3),
1559371c9d4SSatish Balay GmshCellEntry(119, PYR, 3, 4), GmshCellEntry(120, PYR, 3, 5), GmshCellEntry(121, PYR, 3, 6),
1569371c9d4SSatish Balay GmshCellEntry(122, PYR, 3, 7), GmshCellEntry(123, PYR, 3, 8), GmshCellEntry(124, PYR, 3, 9),
157066ea43fSLisandro Dalcin GmshCellEntry(-1, PYR, 3, 10)
1580598e1a2SLisandro Dalcin
1590598e1a2SLisandro Dalcin #if 0
160066ea43fSLisandro Dalcin {20, GMSH_TRI, 2, 3, 3, 9, NULL},
161066ea43fSLisandro Dalcin {18, GMSH_PRI, 3, 2, 6, 15, NULL},
162066ea43fSLisandro Dalcin {19, GMSH_PYR, 3, 2, 5, 13, NULL},
1630598e1a2SLisandro Dalcin #endif
1640598e1a2SLisandro Dalcin };
1650598e1a2SLisandro Dalcin
1660598e1a2SLisandro Dalcin static GmshCellInfo GmshCellMap[150];
1670598e1a2SLisandro Dalcin
GmshCellInfoSetUp(void)168d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshCellInfoSetUp(void)
169d71ae5a4SJacob Faibussowitsch {
1700598e1a2SLisandro Dalcin size_t i, n;
1710598e1a2SLisandro Dalcin static PetscBool called = PETSC_FALSE;
1720598e1a2SLisandro Dalcin
1730598e1a2SLisandro Dalcin PetscFunctionBegin;
1744d86920dSPierre Jolivet if (called) PetscFunctionReturn(PETSC_SUCCESS);
1750598e1a2SLisandro Dalcin called = PETSC_TRUE;
176dd39110bSPierre Jolivet n = PETSC_STATIC_ARRAY_LENGTH(GmshCellMap);
1770598e1a2SLisandro Dalcin for (i = 0; i < n; ++i) {
1780598e1a2SLisandro Dalcin GmshCellMap[i].cellType = -1;
179066ea43fSLisandro Dalcin GmshCellMap[i].polytope = -1;
1800598e1a2SLisandro Dalcin }
181dd39110bSPierre Jolivet n = PETSC_STATIC_ARRAY_LENGTH(GmshCellTable);
182066ea43fSLisandro Dalcin for (i = 0; i < n; ++i) {
183066ea43fSLisandro Dalcin if (GmshCellTable[i].cellType <= 0) continue;
184066ea43fSLisandro Dalcin GmshCellMap[GmshCellTable[i].cellType] = GmshCellTable[i];
185066ea43fSLisandro Dalcin }
1863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1870598e1a2SLisandro Dalcin }
1880598e1a2SLisandro Dalcin
1899371c9d4SSatish Balay #define GmshCellTypeCheck(ct) \
1909371c9d4SSatish 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_); \
1919371c9d4SSatish Balay PetscCheck(GmshCellMap[_ct_].polytope != -1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported Gmsh element type %d", _ct_);)
1920598e1a2SLisandro Dalcin
1930598e1a2SLisandro Dalcin typedef struct {
194698a79b9SLisandro Dalcin PetscViewer viewer;
195698a79b9SLisandro Dalcin int fileFormat;
196698a79b9SLisandro Dalcin int dataSize;
197698a79b9SLisandro Dalcin PetscBool binary;
198698a79b9SLisandro Dalcin PetscBool byteSwap;
199698a79b9SLisandro Dalcin size_t wlen;
200698a79b9SLisandro Dalcin void *wbuf;
201698a79b9SLisandro Dalcin size_t slen;
202698a79b9SLisandro Dalcin void *sbuf;
2030598e1a2SLisandro Dalcin PetscInt *nbuf;
2040598e1a2SLisandro Dalcin PetscInt nodeStart;
2050598e1a2SLisandro Dalcin PetscInt nodeEnd;
20633a088b6SMatthew G. Knepley PetscInt *nodeMap;
207698a79b9SLisandro Dalcin } GmshFile;
208de78e4feSLisandro Dalcin
2096497c311SBarry Smith /*
2106497c311SBarry Smith Returns an array of count items each with a sizeof(eltsize)
2116497c311SBarry Smith */
GmshBufferGet(GmshFile * gmsh,PetscCount count,size_t eltsize,void * buf)2126497c311SBarry Smith static PetscErrorCode GmshBufferGet(GmshFile *gmsh, PetscCount count, size_t eltsize, void *buf)
213d71ae5a4SJacob Faibussowitsch {
214de78e4feSLisandro Dalcin size_t size = count * eltsize;
21511c56cb0SLisandro Dalcin
21611c56cb0SLisandro Dalcin PetscFunctionBegin;
217698a79b9SLisandro Dalcin if (gmsh->wlen < size) {
2189566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->wbuf));
2199566063dSJacob Faibussowitsch PetscCall(PetscMalloc(size, &gmsh->wbuf));
220698a79b9SLisandro Dalcin gmsh->wlen = size;
221de78e4feSLisandro Dalcin }
222698a79b9SLisandro Dalcin *(void **)buf = size ? gmsh->wbuf : NULL;
2233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
224de78e4feSLisandro Dalcin }
225de78e4feSLisandro Dalcin
2266497c311SBarry Smith /*
2276497c311SBarry Smith Returns an array of count items each with the size determined by the GmshFile
2286497c311SBarry Smith */
GmshBufferSizeGet(GmshFile * gmsh,PetscCount count,void * buf)2296497c311SBarry Smith static PetscErrorCode GmshBufferSizeGet(GmshFile *gmsh, PetscCount count, void *buf)
230d71ae5a4SJacob Faibussowitsch {
231698a79b9SLisandro Dalcin size_t dataSize = (size_t)gmsh->dataSize;
232698a79b9SLisandro Dalcin size_t size = count * dataSize;
233698a79b9SLisandro Dalcin
234698a79b9SLisandro Dalcin PetscFunctionBegin;
235698a79b9SLisandro Dalcin if (gmsh->slen < size) {
2369566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->sbuf));
2379566063dSJacob Faibussowitsch PetscCall(PetscMalloc(size, &gmsh->sbuf));
238698a79b9SLisandro Dalcin gmsh->slen = size;
239698a79b9SLisandro Dalcin }
240698a79b9SLisandro Dalcin *(void **)buf = size ? gmsh->sbuf : NULL;
2413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
242698a79b9SLisandro Dalcin }
243698a79b9SLisandro Dalcin
2446497c311SBarry Smith /*
2456497c311SBarry Smith Reads an array of count items each with the size determined by the PetscDataType
2466497c311SBarry Smith */
GmshRead(GmshFile * gmsh,void * buf,PetscCount count,PetscDataType dtype)2476497c311SBarry Smith static PetscErrorCode GmshRead(GmshFile *gmsh, void *buf, PetscCount count, PetscDataType dtype)
248d71ae5a4SJacob Faibussowitsch {
2496497c311SBarry Smith PetscInt icount;
2506497c311SBarry Smith
251de78e4feSLisandro Dalcin PetscFunctionBegin;
2526497c311SBarry Smith PetscCall(PetscIntCast(count, &icount));
2536497c311SBarry Smith PetscCall(PetscViewerRead(gmsh->viewer, buf, icount, NULL, dtype));
2546497c311SBarry Smith if (gmsh->byteSwap) PetscCall(PetscByteSwap(buf, dtype, icount));
2553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
256698a79b9SLisandro Dalcin }
257698a79b9SLisandro Dalcin
GmshReadString(GmshFile * gmsh,char * buf,PetscCount count)2586497c311SBarry Smith static PetscErrorCode GmshReadString(GmshFile *gmsh, char *buf, PetscCount count)
259d71ae5a4SJacob Faibussowitsch {
2606497c311SBarry Smith PetscInt icount;
2616497c311SBarry Smith
262698a79b9SLisandro Dalcin PetscFunctionBegin;
2636497c311SBarry Smith PetscCall(PetscIntCast(count, &icount));
2646497c311SBarry Smith PetscCall(PetscViewerRead(gmsh->viewer, buf, icount, NULL, PETSC_STRING));
2653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
266698a79b9SLisandro Dalcin }
267698a79b9SLisandro Dalcin
GmshMatch(PETSC_UNUSED GmshFile * gmsh,const char Section[],char line[PETSC_MAX_PATH_LEN],PetscBool * match)268d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshMatch(PETSC_UNUSED GmshFile *gmsh, const char Section[], char line[PETSC_MAX_PATH_LEN], PetscBool *match)
269d71ae5a4SJacob Faibussowitsch {
270d6689ca9SLisandro Dalcin PetscFunctionBegin;
2719566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(line, Section, match));
2723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
273d6689ca9SLisandro Dalcin }
274d6689ca9SLisandro Dalcin
GmshExpect(GmshFile * gmsh,const char Section[],char line[PETSC_MAX_PATH_LEN])275d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshExpect(GmshFile *gmsh, const char Section[], char line[PETSC_MAX_PATH_LEN])
276d71ae5a4SJacob Faibussowitsch {
277d6689ca9SLisandro Dalcin PetscBool match;
278d6689ca9SLisandro Dalcin
279d6689ca9SLisandro Dalcin PetscFunctionBegin;
2809566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, Section, line, &match));
28100045ab3SPierre Jolivet PetscCheck(match, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file, expecting %s, not %s", Section, line);
2823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
283d6689ca9SLisandro Dalcin }
284d6689ca9SLisandro Dalcin
GmshReadSection(GmshFile * gmsh,char line[PETSC_MAX_PATH_LEN])285d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadSection(GmshFile *gmsh, char line[PETSC_MAX_PATH_LEN])
286d71ae5a4SJacob Faibussowitsch {
287d6689ca9SLisandro Dalcin PetscBool match;
288d6689ca9SLisandro Dalcin
289d6689ca9SLisandro Dalcin PetscFunctionBegin;
290d6689ca9SLisandro Dalcin while (PETSC_TRUE) {
2919566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 1));
2929566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, "$Comments", line, &match));
293d6689ca9SLisandro Dalcin if (!match) break;
294d6689ca9SLisandro Dalcin while (PETSC_TRUE) {
2959566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 1));
2969566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, "$EndComments", line, &match));
297d6689ca9SLisandro Dalcin if (match) break;
298d6689ca9SLisandro Dalcin }
299d6689ca9SLisandro Dalcin }
3003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
301d6689ca9SLisandro Dalcin }
302d6689ca9SLisandro Dalcin
GmshReadEndSection(GmshFile * gmsh,const char EndSection[],char line[PETSC_MAX_PATH_LEN])303d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEndSection(GmshFile *gmsh, const char EndSection[], char line[PETSC_MAX_PATH_LEN])
304d71ae5a4SJacob Faibussowitsch {
305d6689ca9SLisandro Dalcin PetscFunctionBegin;
3069566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 1));
3079566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, EndSection, line));
3083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
309d6689ca9SLisandro Dalcin }
310d6689ca9SLisandro Dalcin
3116497c311SBarry Smith /*
3126497c311SBarry Smith Read into buf[] count number of PetscInt integers (the file storage size may be different than PetscInt)
3136497c311SBarry Smith */
GmshReadPetscInt(GmshFile * gmsh,PetscInt * buf,PetscCount count)3146497c311SBarry Smith static PetscErrorCode GmshReadPetscInt(GmshFile *gmsh, PetscInt *buf, PetscCount count)
315d71ae5a4SJacob Faibussowitsch {
3166497c311SBarry Smith PetscCount i;
317698a79b9SLisandro Dalcin size_t dataSize = (size_t)gmsh->dataSize;
318698a79b9SLisandro Dalcin
319698a79b9SLisandro Dalcin PetscFunctionBegin;
320698a79b9SLisandro Dalcin if (dataSize == sizeof(PetscInt)) {
3219566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, buf, count, PETSC_INT));
322698a79b9SLisandro Dalcin } else if (dataSize == sizeof(int)) {
323698a79b9SLisandro Dalcin int *ibuf = NULL;
3249566063dSJacob Faibussowitsch PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf));
3259566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, ibuf, count, PETSC_ENUM));
326698a79b9SLisandro Dalcin for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i];
327698a79b9SLisandro Dalcin } else if (dataSize == sizeof(long)) {
328698a79b9SLisandro Dalcin long *ibuf = NULL;
3299566063dSJacob Faibussowitsch PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf));
3309566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, ibuf, count, PETSC_LONG));
331698a79b9SLisandro Dalcin for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i];
332698a79b9SLisandro Dalcin } else if (dataSize == sizeof(PetscInt64)) {
333698a79b9SLisandro Dalcin PetscInt64 *ibuf = NULL;
3349566063dSJacob Faibussowitsch PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf));
3359566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, ibuf, count, PETSC_INT64));
336698a79b9SLisandro Dalcin for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i];
337698a79b9SLisandro Dalcin }
3383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
339698a79b9SLisandro Dalcin }
340698a79b9SLisandro Dalcin
3416497c311SBarry Smith /*
3426497c311SBarry Smith Read into buf[] count number of PetscCount integers (the file storage size may be different than PetscCount)
3436497c311SBarry Smith */
GmshReadPetscCount(GmshFile * gmsh,PetscCount * buf,PetscCount count)3446497c311SBarry Smith static PetscErrorCode GmshReadPetscCount(GmshFile *gmsh, PetscCount *buf, PetscCount count)
3456497c311SBarry Smith {
3466497c311SBarry Smith PetscCount i;
3476497c311SBarry Smith size_t dataSize = (size_t)gmsh->dataSize;
3486497c311SBarry Smith
3496497c311SBarry Smith PetscFunctionBegin;
3506497c311SBarry Smith if (dataSize == sizeof(PetscCount)) {
3516497c311SBarry Smith PetscCall(GmshRead(gmsh, buf, count, PETSC_COUNT));
3526497c311SBarry Smith } else if (dataSize == sizeof(int)) {
3536497c311SBarry Smith int *ibuf = NULL;
3546497c311SBarry Smith PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf));
3556497c311SBarry Smith PetscCall(GmshRead(gmsh, ibuf, count, PETSC_ENUM));
3566497c311SBarry Smith for (i = 0; i < count; ++i) buf[i] = (PetscCount)ibuf[i];
3576497c311SBarry Smith } else if (dataSize == sizeof(long)) {
3586497c311SBarry Smith long *ibuf = NULL;
3596497c311SBarry Smith PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf));
3606497c311SBarry Smith PetscCall(GmshRead(gmsh, ibuf, count, PETSC_LONG));
3616497c311SBarry Smith for (i = 0; i < count; ++i) buf[i] = (PetscCount)ibuf[i];
3626497c311SBarry Smith } else if (dataSize == sizeof(PetscInt64)) {
3636497c311SBarry Smith PetscInt64 *ibuf = NULL;
3646497c311SBarry Smith PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf));
3656497c311SBarry Smith PetscCall(GmshRead(gmsh, ibuf, count, PETSC_INT64));
3666497c311SBarry Smith for (i = 0; i < count; ++i) buf[i] = (PetscCount)ibuf[i];
3676497c311SBarry Smith }
3686497c311SBarry Smith PetscFunctionReturn(PETSC_SUCCESS);
3696497c311SBarry Smith }
3706497c311SBarry Smith
3716497c311SBarry Smith /*
3726497c311SBarry Smith Read into buf[] count number of PetscEnum integers
3736497c311SBarry Smith */
GmshReadInt(GmshFile * gmsh,int * buf,PetscCount count)3746497c311SBarry Smith static PetscErrorCode GmshReadInt(GmshFile *gmsh, int *buf, PetscCount count)
375d71ae5a4SJacob Faibussowitsch {
376698a79b9SLisandro Dalcin PetscFunctionBegin;
3779566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, buf, count, PETSC_ENUM));
3783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
379698a79b9SLisandro Dalcin }
380698a79b9SLisandro Dalcin
3816497c311SBarry Smith /*
3826497c311SBarry Smith Read into buf[] count number of double
3836497c311SBarry Smith */
GmshReadDouble(GmshFile * gmsh,double * buf,PetscCount count)3846497c311SBarry Smith static PetscErrorCode GmshReadDouble(GmshFile *gmsh, double *buf, PetscCount count)
385d71ae5a4SJacob Faibussowitsch {
386698a79b9SLisandro Dalcin PetscFunctionBegin;
3879566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, buf, count, PETSC_DOUBLE));
3883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
389de78e4feSLisandro Dalcin }
390de78e4feSLisandro Dalcin
3919c0edc59SMatthew G. Knepley #define GMSH_MAX_TAGS 16
3927d5b9244SMatthew G. Knepley
393de78e4feSLisandro Dalcin typedef struct {
3940598e1a2SLisandro Dalcin PetscInt id; /* Entity ID */
3950598e1a2SLisandro Dalcin PetscInt dim; /* Dimension */
396de78e4feSLisandro Dalcin double bbox[6]; /* Bounding box */
397de78e4feSLisandro Dalcin PetscInt numTags; /* Size of tag array */
3987d5b9244SMatthew G. Knepley int tags[GMSH_MAX_TAGS]; /* Tag array */
399de78e4feSLisandro Dalcin } GmshEntity;
400de78e4feSLisandro Dalcin
401de78e4feSLisandro Dalcin typedef struct {
402730356f6SLisandro Dalcin GmshEntity *entity[4];
403730356f6SLisandro Dalcin PetscHMapI entityMap[4];
404730356f6SLisandro Dalcin } GmshEntities;
405730356f6SLisandro Dalcin
GmshEntitiesCreate(PetscCount count[4],GmshEntities ** entities)4066497c311SBarry Smith static PetscErrorCode GmshEntitiesCreate(PetscCount count[4], GmshEntities **entities)
407d71ae5a4SJacob Faibussowitsch {
408730356f6SLisandro Dalcin PetscFunctionBegin;
4099566063dSJacob Faibussowitsch PetscCall(PetscNew(entities));
4106497c311SBarry Smith for (PetscInt dim = 0; dim < 4; ++dim) {
4119566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(count[dim], &(*entities)->entity[dim]));
4129566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&(*entities)->entityMap[dim]));
413730356f6SLisandro Dalcin }
4143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
415730356f6SLisandro Dalcin }
416730356f6SLisandro Dalcin
GmshEntitiesDestroy(GmshEntities ** entities)417d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshEntitiesDestroy(GmshEntities **entities)
418d71ae5a4SJacob Faibussowitsch {
4190598e1a2SLisandro Dalcin PetscInt dim;
4200598e1a2SLisandro Dalcin
4210598e1a2SLisandro Dalcin PetscFunctionBegin;
4223ba16761SJacob Faibussowitsch if (!*entities) PetscFunctionReturn(PETSC_SUCCESS);
4230598e1a2SLisandro Dalcin for (dim = 0; dim < 4; ++dim) {
4249566063dSJacob Faibussowitsch PetscCall(PetscFree((*entities)->entity[dim]));
4259566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&(*entities)->entityMap[dim]));
4260598e1a2SLisandro Dalcin }
427f4f49eeaSPierre Jolivet PetscCall(PetscFree(*entities));
4283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
4290598e1a2SLisandro Dalcin }
4300598e1a2SLisandro Dalcin
GmshEntitiesAdd(GmshEntities * entities,PetscInt index,PetscInt dim,PetscInt eid,GmshEntity ** entity)431d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshEntitiesAdd(GmshEntities *entities, PetscInt index, PetscInt dim, PetscInt eid, GmshEntity **entity)
432d71ae5a4SJacob Faibussowitsch {
433730356f6SLisandro Dalcin PetscFunctionBegin;
4349566063dSJacob Faibussowitsch PetscCall(PetscHMapISet(entities->entityMap[dim], eid, index));
435730356f6SLisandro Dalcin entities->entity[dim][index].dim = dim;
436730356f6SLisandro Dalcin entities->entity[dim][index].id = eid;
437730356f6SLisandro Dalcin if (entity) *entity = &entities->entity[dim][index];
4383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
439730356f6SLisandro Dalcin }
440730356f6SLisandro Dalcin
GmshEntitiesGet(GmshEntities * entities,PetscInt dim,PetscInt eid,GmshEntity ** entity)441d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshEntitiesGet(GmshEntities *entities, PetscInt dim, PetscInt eid, GmshEntity **entity)
442d71ae5a4SJacob Faibussowitsch {
443730356f6SLisandro Dalcin PetscInt index;
444730356f6SLisandro Dalcin
445730356f6SLisandro Dalcin PetscFunctionBegin;
4469566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(entities->entityMap[dim], eid, &index));
447730356f6SLisandro Dalcin *entity = &entities->entity[dim][index];
4483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
449730356f6SLisandro Dalcin }
450730356f6SLisandro Dalcin
4510598e1a2SLisandro Dalcin typedef struct {
4520598e1a2SLisandro Dalcin PetscInt *id; /* Node IDs */
4530598e1a2SLisandro Dalcin double *xyz; /* Coordinates */
45481a1af93SMatthew G. Knepley PetscInt *tag; /* Physical tag */
4550598e1a2SLisandro Dalcin } GmshNodes;
4560598e1a2SLisandro Dalcin
GmshNodesCreate(PetscCount count,GmshNodes ** nodes)4576497c311SBarry Smith static PetscErrorCode GmshNodesCreate(PetscCount count, GmshNodes **nodes)
458d71ae5a4SJacob Faibussowitsch {
459730356f6SLisandro Dalcin PetscFunctionBegin;
4609566063dSJacob Faibussowitsch PetscCall(PetscNew(nodes));
4619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(count * 1, &(*nodes)->id));
4629566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(count * 3, &(*nodes)->xyz));
4637d5b9244SMatthew G. Knepley PetscCall(PetscMalloc1(count * GMSH_MAX_TAGS, &(*nodes)->tag));
4643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
465730356f6SLisandro Dalcin }
4660598e1a2SLisandro Dalcin
GmshNodesDestroy(GmshNodes ** nodes)467d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshNodesDestroy(GmshNodes **nodes)
468d71ae5a4SJacob Faibussowitsch {
4690598e1a2SLisandro Dalcin PetscFunctionBegin;
4703ba16761SJacob Faibussowitsch if (!*nodes) PetscFunctionReturn(PETSC_SUCCESS);
4719566063dSJacob Faibussowitsch PetscCall(PetscFree((*nodes)->id));
4729566063dSJacob Faibussowitsch PetscCall(PetscFree((*nodes)->xyz));
4739566063dSJacob Faibussowitsch PetscCall(PetscFree((*nodes)->tag));
474f4f49eeaSPierre Jolivet PetscCall(PetscFree(*nodes));
4753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
476730356f6SLisandro Dalcin }
477730356f6SLisandro Dalcin
478730356f6SLisandro Dalcin typedef struct {
4790598e1a2SLisandro Dalcin PetscInt id; /* Element ID */
4800598e1a2SLisandro Dalcin PetscInt dim; /* Dimension */
481de78e4feSLisandro Dalcin PetscInt cellType; /* Cell type */
4820598e1a2SLisandro Dalcin PetscInt numVerts; /* Size of vertex array */
483de78e4feSLisandro Dalcin PetscInt numNodes; /* Size of node array */
4840598e1a2SLisandro Dalcin PetscInt *nodes; /* Vertex/Node array */
48581a1af93SMatthew G. Knepley PetscInt numTags; /* Size of physical tag array */
4867d5b9244SMatthew G. Knepley int tags[GMSH_MAX_TAGS]; /* Physical tag array */
487de78e4feSLisandro Dalcin } GmshElement;
488de78e4feSLisandro Dalcin
GmshElementsCreate(PetscCount count,GmshElement ** elements)4896497c311SBarry Smith static PetscErrorCode GmshElementsCreate(PetscCount count, GmshElement **elements)
490d71ae5a4SJacob Faibussowitsch {
4910598e1a2SLisandro Dalcin PetscFunctionBegin;
4929566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(count, elements));
4933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
4940598e1a2SLisandro Dalcin }
4950598e1a2SLisandro Dalcin
GmshElementsDestroy(GmshElement ** elements)496d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshElementsDestroy(GmshElement **elements)
497d71ae5a4SJacob Faibussowitsch {
4980598e1a2SLisandro Dalcin PetscFunctionBegin;
4993ba16761SJacob Faibussowitsch if (!*elements) PetscFunctionReturn(PETSC_SUCCESS);
5009566063dSJacob Faibussowitsch PetscCall(PetscFree(*elements));
5013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
5020598e1a2SLisandro Dalcin }
5030598e1a2SLisandro Dalcin
5040598e1a2SLisandro Dalcin typedef struct {
5050598e1a2SLisandro Dalcin PetscInt dim;
506066ea43fSLisandro Dalcin PetscInt order;
5070598e1a2SLisandro Dalcin GmshEntities *entities;
5080598e1a2SLisandro Dalcin PetscInt numNodes;
5090598e1a2SLisandro Dalcin GmshNodes *nodelist;
5100598e1a2SLisandro Dalcin PetscInt numElems;
5110598e1a2SLisandro Dalcin GmshElement *elements;
5120598e1a2SLisandro Dalcin PetscInt numVerts;
5130598e1a2SLisandro Dalcin PetscInt numCells;
5140598e1a2SLisandro Dalcin PetscInt *periodMap;
5150598e1a2SLisandro Dalcin PetscInt *vertexMap;
5160598e1a2SLisandro Dalcin PetscSegBuffer segbuf;
517a45dabc8SMatthew G. Knepley PetscInt numRegions;
51890d778b8SLisandro Dalcin PetscInt *regionDims;
519a45dabc8SMatthew G. Knepley PetscInt *regionTags;
520a45dabc8SMatthew G. Knepley char **regionNames;
5210598e1a2SLisandro Dalcin } GmshMesh;
5220598e1a2SLisandro Dalcin
GmshMeshCreate(GmshMesh ** mesh)523d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshMeshCreate(GmshMesh **mesh)
524d71ae5a4SJacob Faibussowitsch {
5250598e1a2SLisandro Dalcin PetscFunctionBegin;
5269566063dSJacob Faibussowitsch PetscCall(PetscNew(mesh));
5279566063dSJacob Faibussowitsch PetscCall(PetscSegBufferCreate(sizeof(PetscInt), 0, &(*mesh)->segbuf));
5283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
5290598e1a2SLisandro Dalcin }
5300598e1a2SLisandro Dalcin
GmshMeshDestroy(GmshMesh ** mesh)531d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshMeshDestroy(GmshMesh **mesh)
532d71ae5a4SJacob Faibussowitsch {
533a45dabc8SMatthew G. Knepley PetscInt r;
5340598e1a2SLisandro Dalcin
5350598e1a2SLisandro Dalcin PetscFunctionBegin;
5363ba16761SJacob Faibussowitsch if (!*mesh) PetscFunctionReturn(PETSC_SUCCESS);
5379566063dSJacob Faibussowitsch PetscCall(GmshEntitiesDestroy(&(*mesh)->entities));
5389566063dSJacob Faibussowitsch PetscCall(GmshNodesDestroy(&(*mesh)->nodelist));
5399566063dSJacob Faibussowitsch PetscCall(GmshElementsDestroy(&(*mesh)->elements));
5409566063dSJacob Faibussowitsch PetscCall(PetscFree((*mesh)->periodMap));
5419566063dSJacob Faibussowitsch PetscCall(PetscFree((*mesh)->vertexMap));
5429566063dSJacob Faibussowitsch PetscCall(PetscSegBufferDestroy(&(*mesh)->segbuf));
5439566063dSJacob Faibussowitsch for (r = 0; r < (*mesh)->numRegions; ++r) PetscCall(PetscFree((*mesh)->regionNames[r]));
54490d778b8SLisandro Dalcin PetscCall(PetscFree3((*mesh)->regionDims, (*mesh)->regionTags, (*mesh)->regionNames));
545f4f49eeaSPierre Jolivet PetscCall(PetscFree(*mesh));
5463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
5470598e1a2SLisandro Dalcin }
5480598e1a2SLisandro Dalcin
GmshReadNodes_v22(GmshFile * gmsh,GmshMesh * mesh)549d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes_v22(GmshFile *gmsh, GmshMesh *mesh)
550d71ae5a4SJacob Faibussowitsch {
551698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer;
552698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap;
553de78e4feSLisandro Dalcin char line[PETSC_MAX_PATH_LEN];
5547d5b9244SMatthew G. Knepley int n, t, num, nid, snum;
5550598e1a2SLisandro Dalcin GmshNodes *nodes;
556de78e4feSLisandro Dalcin
557de78e4feSLisandro Dalcin PetscFunctionBegin;
5589566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING));
559698a79b9SLisandro Dalcin snum = sscanf(line, "%d", &num);
56008401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
5619566063dSJacob Faibussowitsch PetscCall(GmshNodesCreate(num, &nodes));
5620598e1a2SLisandro Dalcin mesh->numNodes = num;
5630598e1a2SLisandro Dalcin mesh->nodelist = nodes;
5640598e1a2SLisandro Dalcin for (n = 0; n < num; ++n) {
5650598e1a2SLisandro Dalcin double *xyz = nodes->xyz + n * 3;
5669566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM));
5679566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE));
5689566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nid, PETSC_ENUM, 1));
5699566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(xyz, PETSC_DOUBLE, 3));
5700598e1a2SLisandro Dalcin nodes->id[n] = nid;
5717d5b9244SMatthew G. Knepley for (t = 0; t < GMSH_MAX_TAGS; ++t) nodes->tag[n * GMSH_MAX_TAGS + t] = -1;
57211c56cb0SLisandro Dalcin }
5733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
57411c56cb0SLisandro Dalcin }
57511c56cb0SLisandro Dalcin
576de78e4feSLisandro Dalcin /* Gmsh elements can be of any dimension/co-dimension, so we need to traverse the
577de78e4feSLisandro Dalcin file contents multiple times to figure out the true number of cells and facets
578de78e4feSLisandro Dalcin in the given mesh. To make this more efficient we read the file contents only
579de78e4feSLisandro Dalcin once and store them in memory, while determining the true number of cells. */
GmshReadElements_v22(GmshFile * gmsh,GmshMesh * mesh)580d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements_v22(GmshFile *gmsh, GmshMesh *mesh)
581d71ae5a4SJacob Faibussowitsch {
582698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer;
583698a79b9SLisandro Dalcin PetscBool binary = gmsh->binary;
584698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap;
585de78e4feSLisandro Dalcin char line[PETSC_MAX_PATH_LEN];
5860598e1a2SLisandro Dalcin int i, c, p, num, ibuf[1 + 4 + 1000], snum;
5870598e1a2SLisandro Dalcin int cellType, numElem, numVerts, numNodes, numTags;
588df032b82SMatthew G. Knepley GmshElement *elements;
5890598e1a2SLisandro Dalcin PetscInt *nodeMap = gmsh->nodeMap;
590df032b82SMatthew G. Knepley
591df032b82SMatthew G. Knepley PetscFunctionBegin;
5929566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING));
593698a79b9SLisandro Dalcin snum = sscanf(line, "%d", &num);
59408401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
5959566063dSJacob Faibussowitsch PetscCall(GmshElementsCreate(num, &elements));
5960598e1a2SLisandro Dalcin mesh->numElems = num;
5970598e1a2SLisandro Dalcin mesh->elements = elements;
598698a79b9SLisandro Dalcin for (c = 0; c < num;) {
5999566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM));
6009566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, 3));
6010598e1a2SLisandro Dalcin
6020598e1a2SLisandro Dalcin cellType = binary ? ibuf[0] : ibuf[1];
6030598e1a2SLisandro Dalcin numElem = binary ? ibuf[1] : 1;
604df032b82SMatthew G. Knepley numTags = ibuf[2];
6050598e1a2SLisandro Dalcin
6069566063dSJacob Faibussowitsch PetscCall(GmshCellTypeCheck(cellType));
6070598e1a2SLisandro Dalcin numVerts = GmshCellMap[cellType].numVerts;
6080598e1a2SLisandro Dalcin numNodes = GmshCellMap[cellType].numNodes;
6090598e1a2SLisandro Dalcin
610df032b82SMatthew G. Knepley for (i = 0; i < numElem; ++i, ++c) {
6110598e1a2SLisandro Dalcin GmshElement *element = elements + c;
6120598e1a2SLisandro Dalcin const int off = binary ? 0 : 1, nint = 1 + numTags + numNodes - off;
6130598e1a2SLisandro Dalcin const int *id = ibuf, *nodes = ibuf + 1 + numTags, *tags = ibuf + 1;
6149566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf + off, nint, NULL, PETSC_ENUM));
6159566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf + off, PETSC_ENUM, nint));
6160598e1a2SLisandro Dalcin element->id = id[0];
6170598e1a2SLisandro Dalcin element->dim = GmshCellMap[cellType].dim;
6180598e1a2SLisandro Dalcin element->cellType = cellType;
6190598e1a2SLisandro Dalcin element->numVerts = numVerts;
6200598e1a2SLisandro Dalcin element->numNodes = numNodes;
6217d5b9244SMatthew G. Knepley element->numTags = PetscMin(numTags, GMSH_MAX_TAGS);
6229566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes));
6230598e1a2SLisandro Dalcin for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]];
6240598e1a2SLisandro Dalcin for (p = 0; p < element->numTags; p++) element->tags[p] = tags[p];
625df032b82SMatthew G. Knepley }
626df032b82SMatthew G. Knepley }
6273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
628df032b82SMatthew G. Knepley }
6297d282ae0SMichael Lange
630de78e4feSLisandro Dalcin /*
631de78e4feSLisandro Dalcin $Entities
632de78e4feSLisandro Dalcin numPoints(unsigned long) numCurves(unsigned long)
633de78e4feSLisandro Dalcin numSurfaces(unsigned long) numVolumes(unsigned long)
634de78e4feSLisandro Dalcin // points
635de78e4feSLisandro Dalcin tag(int) boxMinX(double) boxMinY(double) boxMinZ(double)
636de78e4feSLisandro Dalcin boxMaxX(double) boxMaxY(double) boxMaxZ(double)
637de78e4feSLisandro Dalcin numPhysicals(unsigned long) phyisicalTag[...](int)
638de78e4feSLisandro Dalcin ...
639de78e4feSLisandro Dalcin // curves
640de78e4feSLisandro Dalcin tag(int) boxMinX(double) boxMinY(double) boxMinZ(double)
641de78e4feSLisandro Dalcin boxMaxX(double) boxMaxY(double) boxMaxZ(double)
642de78e4feSLisandro Dalcin numPhysicals(unsigned long) physicalTag[...](int)
643de78e4feSLisandro Dalcin numBREPVert(unsigned long) tagBREPVert[...](int)
644de78e4feSLisandro Dalcin ...
645de78e4feSLisandro Dalcin // surfaces
646de78e4feSLisandro Dalcin tag(int) boxMinX(double) boxMinY(double) boxMinZ(double)
647de78e4feSLisandro Dalcin boxMaxX(double) boxMaxY(double) boxMaxZ(double)
648de78e4feSLisandro Dalcin numPhysicals(unsigned long) physicalTag[...](int)
649de78e4feSLisandro Dalcin numBREPCurve(unsigned long) tagBREPCurve[...](int)
650de78e4feSLisandro Dalcin ...
651de78e4feSLisandro Dalcin // volumes
652de78e4feSLisandro Dalcin tag(int) boxMinX(double) boxMinY(double) boxMinZ(double)
653de78e4feSLisandro Dalcin boxMaxX(double) boxMaxY(double) boxMaxZ(double)
654de78e4feSLisandro Dalcin numPhysicals(unsigned long) physicalTag[...](int)
655de78e4feSLisandro Dalcin numBREPSurfaces(unsigned long) tagBREPSurfaces[...](int)
656de78e4feSLisandro Dalcin ...
657de78e4feSLisandro Dalcin $EndEntities
658de78e4feSLisandro Dalcin */
GmshReadEntities_v40(GmshFile * gmsh,GmshMesh * mesh)659d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEntities_v40(GmshFile *gmsh, GmshMesh *mesh)
660d71ae5a4SJacob Faibussowitsch {
661698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer;
662698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap;
6636497c311SBarry Smith long lnum, lbuf[4];
664730356f6SLisandro Dalcin int dim, eid, numTags, *ibuf, t;
6656497c311SBarry Smith PetscCount index, count[4];
6666497c311SBarry Smith PetscInt i, num;
667a5ba3d71SLisandro Dalcin GmshEntity *entity = NULL;
668de78e4feSLisandro Dalcin
669de78e4feSLisandro Dalcin PetscFunctionBegin;
6709566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, lbuf, 4, NULL, PETSC_LONG));
6719566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(lbuf, PETSC_LONG, 4));
6726497c311SBarry Smith for (i = 0; i < 4; ++i) count[i] = (PetscCount)lbuf[i];
6739566063dSJacob Faibussowitsch PetscCall(GmshEntitiesCreate(count, &mesh->entities));
674de78e4feSLisandro Dalcin for (dim = 0; dim < 4; ++dim) {
675730356f6SLisandro Dalcin for (index = 0; index < count[dim]; ++index) {
6769566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &eid, 1, NULL, PETSC_ENUM));
6779566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&eid, PETSC_ENUM, 1));
6789566063dSJacob Faibussowitsch PetscCall(GmshEntitiesAdd(mesh->entities, (PetscInt)index, dim, eid, &entity));
6799566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, entity->bbox, 6, NULL, PETSC_DOUBLE));
6809566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(entity->bbox, PETSC_DOUBLE, 6));
6816497c311SBarry Smith PetscCall(PetscViewerRead(viewer, &lnum, 1, NULL, PETSC_LONG));
6826497c311SBarry Smith if (byteSwap) PetscCall(PetscByteSwap(&lnum, PETSC_LONG, 1));
6836497c311SBarry Smith PetscCall(PetscIntCast(lnum, &num));
6849566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, num, sizeof(int), &ibuf));
6859566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, num, NULL, PETSC_ENUM));
6869566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, num));
6877d5b9244SMatthew G. Knepley entity->numTags = numTags = (int)PetscMin(num, GMSH_MAX_TAGS);
688de78e4feSLisandro Dalcin for (t = 0; t < numTags; ++t) entity->tags[t] = ibuf[t];
689de78e4feSLisandro Dalcin if (dim == 0) continue;
6906497c311SBarry Smith PetscCall(PetscViewerRead(viewer, &lnum, 1, NULL, PETSC_LONG));
6916497c311SBarry Smith if (byteSwap) PetscCall(PetscByteSwap(&lnum, PETSC_LONG, 1));
6926497c311SBarry Smith PetscCall(GmshBufferGet(gmsh, lnum, sizeof(int), &ibuf));
6936497c311SBarry Smith PetscCall(PetscIntCast(lnum, &num));
6949566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, num, NULL, PETSC_ENUM));
6959566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, num));
696de78e4feSLisandro Dalcin }
697de78e4feSLisandro Dalcin }
6983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
699de78e4feSLisandro Dalcin }
700de78e4feSLisandro Dalcin
701de78e4feSLisandro Dalcin /*
702de78e4feSLisandro Dalcin $Nodes
703de78e4feSLisandro Dalcin numEntityBlocks(unsigned long) numNodes(unsigned long)
704de78e4feSLisandro Dalcin tagEntity(int) dimEntity(int) typeNode(int) numNodes(unsigned long)
705de78e4feSLisandro Dalcin tag(int) x(double) y(double) z(double)
706de78e4feSLisandro Dalcin ...
707de78e4feSLisandro Dalcin ...
708de78e4feSLisandro Dalcin $EndNodes
709de78e4feSLisandro Dalcin */
GmshReadNodes_v40(GmshFile * gmsh,GmshMesh * mesh)710d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes_v40(GmshFile *gmsh, GmshMesh *mesh)
711d71ae5a4SJacob Faibussowitsch {
712698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer;
713698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap;
7147d5b9244SMatthew G. Knepley long block, node, n, t, numEntityBlocks, numTotalNodes, numNodes;
715de78e4feSLisandro Dalcin int info[3], nid;
7160598e1a2SLisandro Dalcin GmshNodes *nodes;
717de78e4feSLisandro Dalcin
718de78e4feSLisandro Dalcin PetscFunctionBegin;
7199566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numEntityBlocks, 1, NULL, PETSC_LONG));
7209566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numEntityBlocks, PETSC_LONG, 1));
7219566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numTotalNodes, 1, NULL, PETSC_LONG));
7229566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numTotalNodes, PETSC_LONG, 1));
7239566063dSJacob Faibussowitsch PetscCall(GmshNodesCreate(numTotalNodes, &nodes));
7246497c311SBarry Smith PetscCall(PetscIntCast(numTotalNodes, &mesh->numNodes));
7250598e1a2SLisandro Dalcin mesh->nodelist = nodes;
7260598e1a2SLisandro Dalcin for (n = 0, block = 0; block < numEntityBlocks; ++block) {
7279566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, info, 3, NULL, PETSC_ENUM));
7289566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numNodes, 1, NULL, PETSC_LONG));
7299566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numNodes, PETSC_LONG, 1));
730698a79b9SLisandro Dalcin if (gmsh->binary) {
731277f51e8SBarry Smith size_t nbytes = sizeof(int) + 3 * sizeof(double);
732da81f932SPierre Jolivet char *cbuf = NULL; /* dummy value to prevent warning from compiler about possible uninitialized value */
7336497c311SBarry Smith PetscInt icnt;
7346497c311SBarry Smith
7359566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, numNodes, nbytes, &cbuf));
7366497c311SBarry Smith PetscCall(PetscIntCast(numNodes * nbytes, &icnt));
7376497c311SBarry Smith PetscCall(PetscViewerRead(viewer, cbuf, icnt, NULL, PETSC_CHAR));
7380598e1a2SLisandro Dalcin for (node = 0; node < numNodes; ++node, ++n) {
739de78e4feSLisandro Dalcin char *cnid = cbuf + node * nbytes, *cxyz = cnid + sizeof(int);
7400598e1a2SLisandro Dalcin double *xyz = nodes->xyz + n * 3;
7416497c311SBarry Smith
7429566063dSJacob Faibussowitsch if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(cnid, PETSC_ENUM, 1));
7439566063dSJacob Faibussowitsch if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(cxyz, PETSC_DOUBLE, 3));
7449566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(&nid, cnid, sizeof(int)));
7459566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(xyz, cxyz, 3 * sizeof(double)));
7469566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nid, PETSC_ENUM, 1));
7479566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(xyz, PETSC_DOUBLE, 3));
7480598e1a2SLisandro Dalcin nodes->id[n] = nid;
7497d5b9244SMatthew G. Knepley for (t = 0; t < GMSH_MAX_TAGS; ++t) nodes->tag[n * GMSH_MAX_TAGS + t] = -1;
750de78e4feSLisandro Dalcin }
751de78e4feSLisandro Dalcin } else {
7520598e1a2SLisandro Dalcin for (node = 0; node < numNodes; ++node, ++n) {
7530598e1a2SLisandro Dalcin double *xyz = nodes->xyz + n * 3;
7546497c311SBarry Smith
7559566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM));
7569566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE));
7579566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nid, PETSC_ENUM, 1));
7589566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(xyz, PETSC_DOUBLE, 3));
7590598e1a2SLisandro Dalcin nodes->id[n] = nid;
7607d5b9244SMatthew G. Knepley for (t = 0; t < GMSH_MAX_TAGS; ++t) nodes->tag[n * GMSH_MAX_TAGS + t] = -1;
761de78e4feSLisandro Dalcin }
762de78e4feSLisandro Dalcin }
763de78e4feSLisandro Dalcin }
7643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
765de78e4feSLisandro Dalcin }
766de78e4feSLisandro Dalcin
767de78e4feSLisandro Dalcin /*
768de78e4feSLisandro Dalcin $Elements
769de78e4feSLisandro Dalcin numEntityBlocks(unsigned long) numElements(unsigned long)
770de78e4feSLisandro Dalcin tagEntity(int) dimEntity(int) typeEle(int) numElements(unsigned long)
771de78e4feSLisandro Dalcin tag(int) numVert[...](int)
772de78e4feSLisandro Dalcin ...
773de78e4feSLisandro Dalcin ...
774de78e4feSLisandro Dalcin $EndElements
775de78e4feSLisandro Dalcin */
GmshReadElements_v40(GmshFile * gmsh,GmshMesh * mesh)776d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements_v40(GmshFile *gmsh, GmshMesh *mesh)
777d71ae5a4SJacob Faibussowitsch {
778698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer;
779698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap;
780de78e4feSLisandro Dalcin long c, block, numEntityBlocks, numTotalElements, elem, numElements;
781de78e4feSLisandro Dalcin int p, info[3], *ibuf = NULL;
7820598e1a2SLisandro Dalcin int eid, dim, cellType, numVerts, numNodes, numTags;
783a5ba3d71SLisandro Dalcin GmshEntity *entity = NULL;
784de78e4feSLisandro Dalcin GmshElement *elements;
7856497c311SBarry Smith PetscInt *nodeMap = gmsh->nodeMap, icnt;
786de78e4feSLisandro Dalcin
787de78e4feSLisandro Dalcin PetscFunctionBegin;
7889566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numEntityBlocks, 1, NULL, PETSC_LONG));
7899566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numEntityBlocks, PETSC_LONG, 1));
7909566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numTotalElements, 1, NULL, PETSC_LONG));
7919566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numTotalElements, PETSC_LONG, 1));
7929566063dSJacob Faibussowitsch PetscCall(GmshElementsCreate(numTotalElements, &elements));
7936497c311SBarry Smith PetscCall(PetscIntCast(numTotalElements, &mesh->numElems));
7940598e1a2SLisandro Dalcin mesh->elements = elements;
795de78e4feSLisandro Dalcin for (c = 0, block = 0; block < numEntityBlocks; ++block) {
7969566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, info, 3, NULL, PETSC_ENUM));
7979566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(info, PETSC_ENUM, 3));
7989371c9d4SSatish Balay eid = info[0];
7999371c9d4SSatish Balay dim = info[1];
8009371c9d4SSatish Balay cellType = info[2];
8019566063dSJacob Faibussowitsch PetscCall(GmshEntitiesGet(mesh->entities, dim, eid, &entity));
8029566063dSJacob Faibussowitsch PetscCall(GmshCellTypeCheck(cellType));
8030598e1a2SLisandro Dalcin numVerts = GmshCellMap[cellType].numVerts;
8040598e1a2SLisandro Dalcin numNodes = GmshCellMap[cellType].numNodes;
8056497c311SBarry Smith numTags = (int)entity->numTags;
8069566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numElements, 1, NULL, PETSC_LONG));
8079566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numElements, PETSC_LONG, 1));
8089566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, (1 + numNodes) * numElements, sizeof(int), &ibuf));
8096497c311SBarry Smith PetscCall(PetscIntCast((1 + numNodes) * numElements, &icnt));
8106497c311SBarry Smith PetscCall(PetscViewerRead(viewer, ibuf, icnt, NULL, PETSC_ENUM));
8119566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, (1 + numNodes) * numElements));
812de78e4feSLisandro Dalcin for (elem = 0; elem < numElements; ++elem, ++c) {
813de78e4feSLisandro Dalcin GmshElement *element = elements + c;
8140598e1a2SLisandro Dalcin const int *id = ibuf + elem * (1 + numNodes), *nodes = id + 1;
8150598e1a2SLisandro Dalcin element->id = id[0];
816de78e4feSLisandro Dalcin element->dim = dim;
817de78e4feSLisandro Dalcin element->cellType = cellType;
8180598e1a2SLisandro Dalcin element->numVerts = numVerts;
819de78e4feSLisandro Dalcin element->numNodes = numNodes;
820de78e4feSLisandro Dalcin element->numTags = numTags;
8219566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes));
8220598e1a2SLisandro Dalcin for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]];
8230598e1a2SLisandro Dalcin for (p = 0; p < element->numTags; p++) element->tags[p] = entity->tags[p];
824de78e4feSLisandro Dalcin }
825de78e4feSLisandro Dalcin }
8263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
827698a79b9SLisandro Dalcin }
828698a79b9SLisandro Dalcin
GmshReadPeriodic_v40(GmshFile * gmsh,PetscInt periodicMap[])829d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPeriodic_v40(GmshFile *gmsh, PetscInt periodicMap[])
830d71ae5a4SJacob Faibussowitsch {
831698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer;
832698a79b9SLisandro Dalcin int fileFormat = gmsh->fileFormat;
833698a79b9SLisandro Dalcin PetscBool binary = gmsh->binary;
834698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap;
835698a79b9SLisandro Dalcin int numPeriodic, snum, i;
836698a79b9SLisandro Dalcin char line[PETSC_MAX_PATH_LEN];
8370598e1a2SLisandro Dalcin PetscInt *nodeMap = gmsh->nodeMap;
838698a79b9SLisandro Dalcin
839698a79b9SLisandro Dalcin PetscFunctionBegin;
840698a79b9SLisandro Dalcin if (fileFormat == 22 || !binary) {
8419566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING));
842698a79b9SLisandro Dalcin snum = sscanf(line, "%d", &numPeriodic);
84308401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
844698a79b9SLisandro Dalcin } else {
8459566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numPeriodic, 1, NULL, PETSC_ENUM));
8469566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numPeriodic, PETSC_ENUM, 1));
847698a79b9SLisandro Dalcin }
848698a79b9SLisandro Dalcin for (i = 0; i < numPeriodic; i++) {
8499dddd249SSatish Balay int ibuf[3], correspondingDim = -1, correspondingTag = -1, primaryTag = -1, correspondingNode, primaryNode;
850698a79b9SLisandro Dalcin long j, nNodes;
851698a79b9SLisandro Dalcin double affine[16];
852698a79b9SLisandro Dalcin
853698a79b9SLisandro Dalcin if (fileFormat == 22 || !binary) {
8549566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 3, NULL, PETSC_STRING));
8559dddd249SSatish Balay snum = sscanf(line, "%d %d %d", &correspondingDim, &correspondingTag, &primaryTag);
85608401ef6SPierre Jolivet PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
857698a79b9SLisandro Dalcin } else {
8589566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM));
8599566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, 3));
8609371c9d4SSatish Balay correspondingDim = ibuf[0];
8619371c9d4SSatish Balay correspondingTag = ibuf[1];
8629371c9d4SSatish Balay primaryTag = ibuf[2];
863698a79b9SLisandro Dalcin }
8649371c9d4SSatish Balay (void)correspondingDim;
8659371c9d4SSatish Balay (void)correspondingTag;
8669371c9d4SSatish Balay (void)primaryTag; /* unused */
867698a79b9SLisandro Dalcin
868698a79b9SLisandro Dalcin if (fileFormat == 22 || !binary) {
8699566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING));
870698a79b9SLisandro Dalcin snum = sscanf(line, "%ld", &nNodes);
8714c500f23SPierre Jolivet if (snum != 1) { /* discard transformation and try again */
8729566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, -PETSC_MAX_PATH_LEN, NULL, PETSC_STRING));
8739566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING));
874698a79b9SLisandro Dalcin snum = sscanf(line, "%ld", &nNodes);
87508401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
876698a79b9SLisandro Dalcin }
877698a79b9SLisandro Dalcin } else {
8789566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &nNodes, 1, NULL, PETSC_LONG));
8799566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nNodes, PETSC_LONG, 1));
8804c500f23SPierre Jolivet if (nNodes == -1) { /* discard transformation and try again */
8819566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, affine, 16, NULL, PETSC_DOUBLE));
8829566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &nNodes, 1, NULL, PETSC_LONG));
8839566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nNodes, PETSC_LONG, 1));
884698a79b9SLisandro Dalcin }
885698a79b9SLisandro Dalcin }
886698a79b9SLisandro Dalcin
887698a79b9SLisandro Dalcin for (j = 0; j < nNodes; j++) {
888698a79b9SLisandro Dalcin if (fileFormat == 22 || !binary) {
8899566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 2, NULL, PETSC_STRING));
8909dddd249SSatish Balay snum = sscanf(line, "%d %d", &correspondingNode, &primaryNode);
89108401ef6SPierre Jolivet PetscCheck(snum == 2, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
892698a79b9SLisandro Dalcin } else {
8939566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, 2, NULL, PETSC_ENUM));
8949566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, 2));
8959371c9d4SSatish Balay correspondingNode = ibuf[0];
8969371c9d4SSatish Balay primaryNode = ibuf[1];
897698a79b9SLisandro Dalcin }
8989dddd249SSatish Balay correspondingNode = (int)nodeMap[correspondingNode];
8999dddd249SSatish Balay primaryNode = (int)nodeMap[primaryNode];
9009dddd249SSatish Balay periodicMap[correspondingNode] = primaryNode;
901698a79b9SLisandro Dalcin }
902698a79b9SLisandro Dalcin }
9033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
904698a79b9SLisandro Dalcin }
905698a79b9SLisandro Dalcin
9060598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
907698a79b9SLisandro Dalcin $Entities
908698a79b9SLisandro Dalcin numPoints(size_t) numCurves(size_t)
909698a79b9SLisandro Dalcin numSurfaces(size_t) numVolumes(size_t)
910698a79b9SLisandro Dalcin pointTag(int) X(double) Y(double) Z(double)
911698a79b9SLisandro Dalcin numPhysicalTags(size_t) physicalTag(int) ...
912698a79b9SLisandro Dalcin ...
913698a79b9SLisandro Dalcin curveTag(int) minX(double) minY(double) minZ(double)
914698a79b9SLisandro Dalcin maxX(double) maxY(double) maxZ(double)
915698a79b9SLisandro Dalcin numPhysicalTags(size_t) physicalTag(int) ...
916698a79b9SLisandro Dalcin numBoundingPoints(size_t) pointTag(int) ...
917698a79b9SLisandro Dalcin ...
918698a79b9SLisandro Dalcin surfaceTag(int) minX(double) minY(double) minZ(double)
919698a79b9SLisandro Dalcin maxX(double) maxY(double) maxZ(double)
920698a79b9SLisandro Dalcin numPhysicalTags(size_t) physicalTag(int) ...
921698a79b9SLisandro Dalcin numBoundingCurves(size_t) curveTag(int) ...
922698a79b9SLisandro Dalcin ...
923698a79b9SLisandro Dalcin volumeTag(int) minX(double) minY(double) minZ(double)
924698a79b9SLisandro Dalcin maxX(double) maxY(double) maxZ(double)
925698a79b9SLisandro Dalcin numPhysicalTags(size_t) physicalTag(int) ...
926698a79b9SLisandro Dalcin numBoundngSurfaces(size_t) surfaceTag(int) ...
927698a79b9SLisandro Dalcin ...
928698a79b9SLisandro Dalcin $EndEntities
929698a79b9SLisandro Dalcin */
GmshReadEntities_v41(GmshFile * gmsh,GmshMesh * mesh)930d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEntities_v41(GmshFile *gmsh, GmshMesh *mesh)
931d71ae5a4SJacob Faibussowitsch {
9326497c311SBarry Smith PetscCount count[4], index, numTags;
933698a79b9SLisandro Dalcin int dim, eid, *tags = NULL;
934698a79b9SLisandro Dalcin GmshEntity *entity = NULL;
935698a79b9SLisandro Dalcin
936698a79b9SLisandro Dalcin PetscFunctionBegin;
9376497c311SBarry Smith PetscCall(GmshReadPetscCount(gmsh, count, 4));
9389566063dSJacob Faibussowitsch PetscCall(GmshEntitiesCreate(count, &mesh->entities));
939698a79b9SLisandro Dalcin for (dim = 0; dim < 4; ++dim) {
940698a79b9SLisandro Dalcin for (index = 0; index < count[dim]; ++index) {
9419566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, &eid, 1));
9429566063dSJacob Faibussowitsch PetscCall(GmshEntitiesAdd(mesh->entities, (PetscInt)index, dim, eid, &entity));
9439566063dSJacob Faibussowitsch PetscCall(GmshReadDouble(gmsh, entity->bbox, (dim == 0) ? 3 : 6));
9446497c311SBarry Smith PetscCall(GmshReadPetscCount(gmsh, &numTags, 1));
9459566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, numTags, sizeof(int), &tags));
9469566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, tags, numTags));
9476497c311SBarry Smith PetscCheck(numTags <= GMSH_MAX_TAGS, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PETSc currently supports up to %" PetscInt_FMT " tags per entity, not %" PetscCount_FMT, (PetscInt)GMSH_MAX_TAGS, numTags);
9486497c311SBarry Smith PetscCall(PetscIntCast(numTags, &entity->numTags));
9496497c311SBarry Smith for (PetscInt i = 0; i < entity->numTags; ++i) entity->tags[i] = tags[i];
950698a79b9SLisandro Dalcin if (dim == 0) continue;
9516497c311SBarry Smith PetscCall(GmshReadPetscCount(gmsh, &numTags, 1));
9529566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, numTags, sizeof(int), &tags));
9539566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, tags, numTags));
95481a1af93SMatthew G. Knepley /* Currently, we do not save the ids for the bounding entities */
955698a79b9SLisandro Dalcin }
956698a79b9SLisandro Dalcin }
9573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
958698a79b9SLisandro Dalcin }
959698a79b9SLisandro Dalcin
96033a088b6SMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
961698a79b9SLisandro Dalcin $Nodes
962698a79b9SLisandro Dalcin numEntityBlocks(size_t) numNodes(size_t)
963698a79b9SLisandro Dalcin minNodeTag(size_t) maxNodeTag(size_t)
964698a79b9SLisandro Dalcin entityDim(int) entityTag(int) parametric(int; 0 or 1) numNodesBlock(size_t)
965698a79b9SLisandro Dalcin nodeTag(size_t)
966698a79b9SLisandro Dalcin ...
967698a79b9SLisandro Dalcin x(double) y(double) z(double)
968698a79b9SLisandro Dalcin < u(double; if parametric and entityDim = 1 or entityDim = 2) >
969698a79b9SLisandro Dalcin < v(double; if parametric and entityDim = 2) >
970698a79b9SLisandro Dalcin ...
971698a79b9SLisandro Dalcin ...
972698a79b9SLisandro Dalcin $EndNodes
973698a79b9SLisandro Dalcin */
GmshReadNodes_v41(GmshFile * gmsh,GmshMesh * mesh)974d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes_v41(GmshFile *gmsh, GmshMesh *mesh)
975d71ae5a4SJacob Faibussowitsch {
97681a1af93SMatthew G. Knepley int info[3], dim, eid, parametric;
9776497c311SBarry Smith PetscCount sizes[4], numEntityBlocks, numNodes, numNodesBlock = 0;
9786497c311SBarry Smith PetscInt numTags;
97981a1af93SMatthew G. Knepley GmshEntity *entity = NULL;
9800598e1a2SLisandro Dalcin GmshNodes *nodes;
981698a79b9SLisandro Dalcin
982698a79b9SLisandro Dalcin PetscFunctionBegin;
9836497c311SBarry Smith PetscCall(GmshReadPetscCount(gmsh, sizes, 4));
9849371c9d4SSatish Balay numEntityBlocks = sizes[0];
9859371c9d4SSatish Balay numNodes = sizes[1];
9869566063dSJacob Faibussowitsch PetscCall(GmshNodesCreate(numNodes, &nodes));
9876497c311SBarry Smith PetscCall(PetscIntCast(numNodes, &mesh->numNodes));
9880598e1a2SLisandro Dalcin mesh->nodelist = nodes;
9896497c311SBarry Smith if (numEntityBlocks && !mesh->entities) PetscCall(PetscInfo(NULL, "File specifies %" PetscCount_FMT " entity blocks, but was missing the $Entities section\n", numEntityBlocks));
9906497c311SBarry Smith for (PetscCount block = 0, node = 0; block < numEntityBlocks; ++block, node += numNodesBlock) {
9919566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, info, 3));
9929371c9d4SSatish Balay dim = info[0];
9939371c9d4SSatish Balay eid = info[1];
9949371c9d4SSatish Balay parametric = info[2];
995e43c9757SMatthew G. Knepley if (mesh->entities) PetscCall(GmshEntitiesGet(mesh->entities, dim, eid, &entity));
996e43c9757SMatthew G. Knepley numTags = entity ? entity->numTags : 0;
99781a1af93SMatthew G. Knepley PetscCheck(!parametric, PETSC_COMM_SELF, PETSC_ERR_SUP, "Parametric coordinates not supported");
9986497c311SBarry Smith PetscCall(GmshReadPetscCount(gmsh, &numNodesBlock, 1));
9996497c311SBarry Smith PetscCall(GmshReadPetscInt(gmsh, nodes->id + node, numNodesBlock));
10009566063dSJacob Faibussowitsch PetscCall(GmshReadDouble(gmsh, nodes->xyz + node * 3, numNodesBlock * 3));
10016497c311SBarry Smith for (PetscCount n = 0; n < numNodesBlock; ++n) {
10027d5b9244SMatthew G. Knepley PetscInt *tags = &nodes->tag[node * GMSH_MAX_TAGS];
10037d5b9244SMatthew G. Knepley
10046497c311SBarry Smith for (PetscInt t = 0; t < numTags; ++t) tags[n * GMSH_MAX_TAGS + t] = entity->tags[t];
10056497c311SBarry Smith for (PetscInt t = numTags; t < GMSH_MAX_TAGS; ++t) tags[n * GMSH_MAX_TAGS + t] = -1;
10067d5b9244SMatthew G. Knepley }
1007698a79b9SLisandro Dalcin }
10086497c311SBarry Smith PetscCall(PetscIntCast(sizes[2], &gmsh->nodeStart));
10096497c311SBarry Smith PetscCall(PetscIntCast(sizes[3] + 1, &gmsh->nodeEnd));
10103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1011698a79b9SLisandro Dalcin }
1012698a79b9SLisandro Dalcin
101333a088b6SMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
1014698a79b9SLisandro Dalcin $Elements
1015698a79b9SLisandro Dalcin numEntityBlocks(size_t) numElements(size_t)
1016698a79b9SLisandro Dalcin minElementTag(size_t) maxElementTag(size_t)
1017698a79b9SLisandro Dalcin entityDim(int) entityTag(int) elementType(int; see below) numElementsBlock(size_t)
1018698a79b9SLisandro Dalcin elementTag(size_t) nodeTag(size_t) ...
1019698a79b9SLisandro Dalcin ...
1020698a79b9SLisandro Dalcin ...
1021698a79b9SLisandro Dalcin $EndElements
1022698a79b9SLisandro Dalcin */
GmshReadElements_v41(GmshFile * gmsh,GmshMesh * mesh)1023d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements_v41(GmshFile *gmsh, GmshMesh *mesh)
1024d71ae5a4SJacob Faibussowitsch {
10250598e1a2SLisandro Dalcin int info[3], eid, dim, cellType;
10266497c311SBarry Smith PetscCount sizes[4], numEntityBlocks, numElements, numBlockElements, numVerts, numNodes, numTags, block, elem, c, p;
1027698a79b9SLisandro Dalcin GmshEntity *entity = NULL;
1028698a79b9SLisandro Dalcin GmshElement *elements;
10296497c311SBarry Smith PetscInt *nodeMap = gmsh->nodeMap, *ibuf = NULL;
1030698a79b9SLisandro Dalcin
1031698a79b9SLisandro Dalcin PetscFunctionBegin;
10326497c311SBarry Smith PetscCall(GmshReadPetscCount(gmsh, sizes, 4));
10339371c9d4SSatish Balay numEntityBlocks = sizes[0];
10349371c9d4SSatish Balay numElements = sizes[1];
10359566063dSJacob Faibussowitsch PetscCall(GmshElementsCreate(numElements, &elements));
10366497c311SBarry Smith PetscCall(PetscIntCast(numElements, &mesh->numElems));
10370598e1a2SLisandro Dalcin mesh->elements = elements;
10386497c311SBarry Smith if (numEntityBlocks && !mesh->entities) PetscCall(PetscInfo(NULL, "File specifies %" PetscCount_FMT " entity blocks, but was missing the $Entities section\n", numEntityBlocks));
1039698a79b9SLisandro Dalcin for (c = 0, block = 0; block < numEntityBlocks; ++block) {
10409566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, info, 3));
10419371c9d4SSatish Balay dim = info[0];
10429371c9d4SSatish Balay eid = info[1];
10439371c9d4SSatish Balay cellType = info[2];
1044e43c9757SMatthew G. Knepley if (mesh->entities) PetscCall(GmshEntitiesGet(mesh->entities, dim, eid, &entity));
10459566063dSJacob Faibussowitsch PetscCall(GmshCellTypeCheck(cellType));
10460598e1a2SLisandro Dalcin numVerts = GmshCellMap[cellType].numVerts;
10470598e1a2SLisandro Dalcin numNodes = GmshCellMap[cellType].numNodes;
1048e43c9757SMatthew G. Knepley numTags = entity ? entity->numTags : 0;
10496497c311SBarry Smith PetscCall(GmshReadPetscCount(gmsh, &numBlockElements, 1));
10509566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, (1 + numNodes) * numBlockElements, sizeof(PetscInt), &ibuf));
10516497c311SBarry Smith PetscCall(GmshReadPetscInt(gmsh, ibuf, (1 + numNodes) * numBlockElements));
1052698a79b9SLisandro Dalcin for (elem = 0; elem < numBlockElements; ++elem, ++c) {
1053698a79b9SLisandro Dalcin GmshElement *element = elements + c;
10540598e1a2SLisandro Dalcin const PetscInt *id = ibuf + elem * (1 + numNodes), *nodes = id + 1;
10556497c311SBarry Smith
1056698a79b9SLisandro Dalcin element->id = id[0];
1057698a79b9SLisandro Dalcin element->dim = dim;
1058698a79b9SLisandro Dalcin element->cellType = cellType;
10596497c311SBarry Smith PetscCall(PetscIntCast(numVerts, &element->numVerts));
10606497c311SBarry Smith PetscCall(PetscIntCast(numNodes, &element->numNodes));
10616497c311SBarry Smith PetscCall(PetscIntCast(numTags, &element->numTags));
10626497c311SBarry Smith PetscCall(PetscSegBufferGet(mesh->segbuf, element->numNodes, &element->nodes));
10630598e1a2SLisandro Dalcin for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]];
10640598e1a2SLisandro Dalcin for (p = 0; p < element->numTags; p++) element->tags[p] = entity->tags[p];
1065698a79b9SLisandro Dalcin }
1066698a79b9SLisandro Dalcin }
10673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1068698a79b9SLisandro Dalcin }
1069698a79b9SLisandro Dalcin
10700598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
1071698a79b9SLisandro Dalcin $Periodic
1072698a79b9SLisandro Dalcin numPeriodicLinks(size_t)
10739dddd249SSatish Balay entityDim(int) entityTag(int) entityTagPrimary(int)
1074698a79b9SLisandro Dalcin numAffine(size_t) value(double) ...
1075698a79b9SLisandro Dalcin numCorrespondingNodes(size_t)
10769dddd249SSatish Balay nodeTag(size_t) nodeTagPrimary(size_t)
1077698a79b9SLisandro Dalcin ...
1078698a79b9SLisandro Dalcin ...
1079698a79b9SLisandro Dalcin $EndPeriodic
1080698a79b9SLisandro Dalcin */
GmshReadPeriodic_v41(GmshFile * gmsh,PetscInt periodicMap[])1081d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPeriodic_v41(GmshFile *gmsh, PetscInt periodicMap[])
1082d71ae5a4SJacob Faibussowitsch {
1083698a79b9SLisandro Dalcin int info[3];
1084698a79b9SLisandro Dalcin double dbuf[16];
10856497c311SBarry Smith PetscCount numPeriodicLinks, numAffine, numCorrespondingNodes;
10866497c311SBarry Smith PetscInt *nodeMap = gmsh->nodeMap, *nodeTags = NULL;
1087698a79b9SLisandro Dalcin
1088698a79b9SLisandro Dalcin PetscFunctionBegin;
10896497c311SBarry Smith PetscCall(GmshReadPetscCount(gmsh, &numPeriodicLinks, 1));
10906497c311SBarry Smith for (PetscCount link = 0; link < numPeriodicLinks; ++link) {
10919566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, info, 3));
10926497c311SBarry Smith PetscCall(GmshReadPetscCount(gmsh, &numAffine, 1));
10939566063dSJacob Faibussowitsch PetscCall(GmshReadDouble(gmsh, dbuf, numAffine));
10946497c311SBarry Smith PetscCall(GmshReadPetscCount(gmsh, &numCorrespondingNodes, 1));
10959566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, numCorrespondingNodes, sizeof(PetscInt), &nodeTags));
10966497c311SBarry Smith PetscCall(GmshReadPetscInt(gmsh, nodeTags, numCorrespondingNodes * 2));
10976497c311SBarry Smith for (PetscCount node = 0; node < numCorrespondingNodes; ++node) {
10989dddd249SSatish Balay PetscInt correspondingNode = nodeMap[nodeTags[node * 2 + 0]];
10999dddd249SSatish Balay PetscInt primaryNode = nodeMap[nodeTags[node * 2 + 1]];
11006497c311SBarry Smith
11019dddd249SSatish Balay periodicMap[correspondingNode] = primaryNode;
1102698a79b9SLisandro Dalcin }
1103698a79b9SLisandro Dalcin }
11043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1105698a79b9SLisandro Dalcin }
1106698a79b9SLisandro Dalcin
11070598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
1108d6689ca9SLisandro Dalcin $MeshFormat // same as MSH version 2
1109d6689ca9SLisandro Dalcin version(ASCII double; currently 4.1)
1110d6689ca9SLisandro Dalcin file-type(ASCII int; 0 for ASCII mode, 1 for binary mode)
1111d6689ca9SLisandro Dalcin data-size(ASCII int; sizeof(size_t))
1112d6689ca9SLisandro Dalcin < int with value one; only in binary mode, to detect endianness >
1113d6689ca9SLisandro Dalcin $EndMeshFormat
1114d6689ca9SLisandro Dalcin */
GmshReadMeshFormat(GmshFile * gmsh)1115d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadMeshFormat(GmshFile *gmsh)
1116d71ae5a4SJacob Faibussowitsch {
1117698a79b9SLisandro Dalcin char line[PETSC_MAX_PATH_LEN];
1118698a79b9SLisandro Dalcin int snum, fileType, fileFormat, dataSize, checkEndian;
1119698a79b9SLisandro Dalcin float version;
1120698a79b9SLisandro Dalcin
1121698a79b9SLisandro Dalcin PetscFunctionBegin;
11229566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 3));
1123698a79b9SLisandro Dalcin snum = sscanf(line, "%f %d %d", &version, &fileType, &dataSize);
1124a8d4e440SJunchao Zhang fileFormat = (int)roundf(version * 10);
112508401ef6SPierre Jolivet PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line);
1126a8d4e440SJunchao Zhang PetscCheck(fileFormat >= 22, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at least 2.2", (double)version);
11271dca8a05SBarry Smith PetscCheck((int)version != 3, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f not supported", (double)version);
1128a8d4e440SJunchao Zhang PetscCheck(fileFormat <= 41, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at most 4.1", (double)version);
112908401ef6SPierre Jolivet PetscCheck(!gmsh->binary || fileType, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Viewer is binary but Gmsh file is ASCII");
113008401ef6SPierre Jolivet PetscCheck(gmsh->binary || !fileType, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Viewer is ASCII but Gmsh file is binary");
11311dca8a05SBarry 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);
11321dca8a05SBarry 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);
1133698a79b9SLisandro Dalcin gmsh->fileFormat = fileFormat;
1134698a79b9SLisandro Dalcin gmsh->dataSize = dataSize;
1135698a79b9SLisandro Dalcin gmsh->byteSwap = PETSC_FALSE;
1136698a79b9SLisandro Dalcin if (gmsh->binary) {
11379566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, &checkEndian, 1));
1138698a79b9SLisandro Dalcin if (checkEndian != 1) {
11399566063dSJacob Faibussowitsch PetscCall(PetscByteSwap(&checkEndian, PETSC_ENUM, 1));
114008401ef6SPierre Jolivet PetscCheck(checkEndian == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to detect endianness in Gmsh file header: %s", line);
1141698a79b9SLisandro Dalcin gmsh->byteSwap = PETSC_TRUE;
1142698a79b9SLisandro Dalcin }
1143698a79b9SLisandro Dalcin }
11443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1145698a79b9SLisandro Dalcin }
1146698a79b9SLisandro Dalcin
11478749820aSMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
11488749820aSMatthew G. Knepley Neper: https://neper.info/ adds this section
11498749820aSMatthew G. Knepley
11508749820aSMatthew G. Knepley $MeshVersion
11518749820aSMatthew G. Knepley <major>.<minor>,<patch>
11528749820aSMatthew G. Knepley $EndMeshVersion
11538749820aSMatthew G. Knepley */
GmshReadMeshVersion(GmshFile * gmsh)11548749820aSMatthew G. Knepley static PetscErrorCode GmshReadMeshVersion(GmshFile *gmsh)
11558749820aSMatthew G. Knepley {
11568749820aSMatthew G. Knepley char line[PETSC_MAX_PATH_LEN];
11578749820aSMatthew G. Knepley int snum, major, minor, patch;
11588749820aSMatthew G. Knepley
11598749820aSMatthew G. Knepley PetscFunctionBegin;
11608749820aSMatthew G. Knepley PetscCall(GmshReadString(gmsh, line, 1));
11618749820aSMatthew G. Knepley snum = sscanf(line, "%d.%d.%d", &major, &minor, &patch);
11628749820aSMatthew G. Knepley PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line);
11638749820aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
11648749820aSMatthew G. Knepley }
11658749820aSMatthew G. Knepley
11668749820aSMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
11678749820aSMatthew G. Knepley Neper: https://neper.info/ adds this section
11688749820aSMatthew G. Knepley
11698749820aSMatthew G. Knepley $Domain
11708749820aSMatthew G. Knepley <shape>
11718749820aSMatthew G. Knepley $EndDomain
11728749820aSMatthew G. Knepley */
GmshReadMeshDomain(GmshFile * gmsh)11738749820aSMatthew G. Knepley static PetscErrorCode GmshReadMeshDomain(GmshFile *gmsh)
11748749820aSMatthew G. Knepley {
11758749820aSMatthew G. Knepley char line[PETSC_MAX_PATH_LEN];
11768749820aSMatthew G. Knepley
11778749820aSMatthew G. Knepley PetscFunctionBegin;
11788749820aSMatthew G. Knepley PetscCall(GmshReadString(gmsh, line, 1));
11798749820aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
11808749820aSMatthew G. Knepley }
11818749820aSMatthew G. Knepley
11821f643af3SLisandro Dalcin /*
11831f643af3SLisandro Dalcin PhysicalNames
11841f643af3SLisandro Dalcin numPhysicalNames(ASCII int)
11851f643af3SLisandro Dalcin dimension(ASCII int) physicalTag(ASCII int) "name"(127 characters max)
11861f643af3SLisandro Dalcin ...
11871f643af3SLisandro Dalcin $EndPhysicalNames
11881f643af3SLisandro Dalcin */
GmshReadPhysicalNames(GmshFile * gmsh,GmshMesh * mesh)1189d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPhysicalNames(GmshFile *gmsh, GmshMesh *mesh)
1190d71ae5a4SJacob Faibussowitsch {
1191bbcf679cSJacob Faibussowitsch char line[PETSC_MAX_PATH_LEN], name[128 + 2], *p = NULL, *q = NULL, *r = NULL;
1192a45dabc8SMatthew G. Knepley int snum, region, dim, tag;
1193698a79b9SLisandro Dalcin
1194698a79b9SLisandro Dalcin PetscFunctionBegin;
11959566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 1));
1196a45dabc8SMatthew G. Knepley snum = sscanf(line, "%d", ®ion);
1197a45dabc8SMatthew G. Knepley mesh->numRegions = region;
119808401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
119990d778b8SLisandro Dalcin PetscCall(PetscMalloc3(mesh->numRegions, &mesh->regionDims, mesh->numRegions, &mesh->regionTags, mesh->numRegions, &mesh->regionNames));
1200a45dabc8SMatthew G. Knepley for (region = 0; region < mesh->numRegions; ++region) {
12019566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 2));
12021f643af3SLisandro Dalcin snum = sscanf(line, "%d %d", &dim, &tag);
120308401ef6SPierre Jolivet PetscCheck(snum == 2, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
12049566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, -(PetscInt)sizeof(line)));
12059566063dSJacob Faibussowitsch PetscCall(PetscStrchr(line, '"', &p));
120628b400f6SJacob Faibussowitsch PetscCheck(p, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
12079566063dSJacob Faibussowitsch PetscCall(PetscStrrchr(line, '"', &q));
120808401ef6SPierre Jolivet PetscCheck(q != p, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
12095f5cd6d5SMatthew G. Knepley PetscCall(PetscStrrchr(line, ':', &r));
12105f5cd6d5SMatthew G. Knepley if (p != r) q = r;
12119566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(name, p + 1, (size_t)(q - p - 1)));
121290d778b8SLisandro Dalcin mesh->regionDims[region] = dim;
1213a45dabc8SMatthew G. Knepley mesh->regionTags[region] = tag;
12149566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(name, &mesh->regionNames[region]));
1215698a79b9SLisandro Dalcin }
12163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1217de78e4feSLisandro Dalcin }
1218de78e4feSLisandro Dalcin
GmshReadEntities(GmshFile * gmsh,GmshMesh * mesh)1219d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEntities(GmshFile *gmsh, GmshMesh *mesh)
1220d71ae5a4SJacob Faibussowitsch {
12210598e1a2SLisandro Dalcin PetscFunctionBegin;
12220598e1a2SLisandro Dalcin switch (gmsh->fileFormat) {
1223d71ae5a4SJacob Faibussowitsch case 41:
1224d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadEntities_v41(gmsh, mesh));
1225d71ae5a4SJacob Faibussowitsch break;
1226d71ae5a4SJacob Faibussowitsch default:
1227d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadEntities_v40(gmsh, mesh));
1228d71ae5a4SJacob Faibussowitsch break;
122996ca5757SLisandro Dalcin }
12303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
12310598e1a2SLisandro Dalcin }
12320598e1a2SLisandro Dalcin
GmshReadNodes(GmshFile * gmsh,GmshMesh * mesh)1233d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes(GmshFile *gmsh, GmshMesh *mesh)
1234d71ae5a4SJacob Faibussowitsch {
12350598e1a2SLisandro Dalcin PetscFunctionBegin;
12360598e1a2SLisandro Dalcin switch (gmsh->fileFormat) {
1237d71ae5a4SJacob Faibussowitsch case 41:
1238d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadNodes_v41(gmsh, mesh));
1239d71ae5a4SJacob Faibussowitsch break;
1240d71ae5a4SJacob Faibussowitsch case 40:
1241d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadNodes_v40(gmsh, mesh));
1242d71ae5a4SJacob Faibussowitsch break;
1243d71ae5a4SJacob Faibussowitsch default:
1244d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadNodes_v22(gmsh, mesh));
1245d71ae5a4SJacob Faibussowitsch break;
12460598e1a2SLisandro Dalcin }
12470598e1a2SLisandro Dalcin
12480598e1a2SLisandro Dalcin { /* Gmsh v2.2/v4.0 does not provide min/max node tags */
12490598e1a2SLisandro Dalcin if (mesh->numNodes > 0 && gmsh->nodeEnd >= gmsh->nodeStart) {
12501690c2aeSBarry Smith PetscInt tagMin = PETSC_INT_MAX, tagMax = PETSC_INT_MIN, n;
12510598e1a2SLisandro Dalcin GmshNodes *nodes = mesh->nodelist;
12520598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) {
12530598e1a2SLisandro Dalcin const PetscInt tag = nodes->id[n];
12540598e1a2SLisandro Dalcin tagMin = PetscMin(tag, tagMin);
12550598e1a2SLisandro Dalcin tagMax = PetscMax(tag, tagMax);
12560598e1a2SLisandro Dalcin }
12570598e1a2SLisandro Dalcin gmsh->nodeStart = tagMin;
12580598e1a2SLisandro Dalcin gmsh->nodeEnd = tagMax + 1;
12590598e1a2SLisandro Dalcin }
12600598e1a2SLisandro Dalcin }
12610598e1a2SLisandro Dalcin
12620598e1a2SLisandro Dalcin { /* Support for sparse node tags */
12630598e1a2SLisandro Dalcin PetscInt n, t;
12640598e1a2SLisandro Dalcin GmshNodes *nodes = mesh->nodelist;
12659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(gmsh->nodeEnd - gmsh->nodeStart, &gmsh->nbuf));
12661690c2aeSBarry Smith for (t = 0; t < gmsh->nodeEnd - gmsh->nodeStart; ++t) gmsh->nbuf[t] = PETSC_INT_MIN;
12670598e1a2SLisandro Dalcin gmsh->nodeMap = gmsh->nbuf - gmsh->nodeStart;
12680598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) {
12690598e1a2SLisandro Dalcin const PetscInt tag = nodes->id[n];
127063a3b9bcSJacob Faibussowitsch PetscCheck(gmsh->nodeMap[tag] < 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Repeated node tag %" PetscInt_FMT, tag);
12710598e1a2SLisandro Dalcin gmsh->nodeMap[tag] = n;
12720598e1a2SLisandro Dalcin }
12730598e1a2SLisandro Dalcin }
12743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
12750598e1a2SLisandro Dalcin }
12760598e1a2SLisandro Dalcin
GmshReadElements(GmshFile * gmsh,GmshMesh * mesh)1277d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements(GmshFile *gmsh, GmshMesh *mesh)
1278d71ae5a4SJacob Faibussowitsch {
12790598e1a2SLisandro Dalcin PetscFunctionBegin;
12800598e1a2SLisandro Dalcin switch (gmsh->fileFormat) {
1281d71ae5a4SJacob Faibussowitsch case 41:
1282d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadElements_v41(gmsh, mesh));
1283d71ae5a4SJacob Faibussowitsch break;
1284d71ae5a4SJacob Faibussowitsch case 40:
1285d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadElements_v40(gmsh, mesh));
1286d71ae5a4SJacob Faibussowitsch break;
1287d71ae5a4SJacob Faibussowitsch default:
1288d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadElements_v22(gmsh, mesh));
1289d71ae5a4SJacob Faibussowitsch break;
12900598e1a2SLisandro Dalcin }
12910598e1a2SLisandro Dalcin
12920598e1a2SLisandro Dalcin { /* Reorder elements by codimension and polytope type */
12930598e1a2SLisandro Dalcin PetscInt ne = mesh->numElems;
12940598e1a2SLisandro Dalcin GmshElement *elements = mesh->elements;
1295066ea43fSLisandro Dalcin PetscInt keymap[GMSH_NUM_POLYTOPES], nk = 0;
1296066ea43fSLisandro Dalcin PetscInt offset[GMSH_NUM_POLYTOPES + 1], e, k;
12970598e1a2SLisandro Dalcin
12981690c2aeSBarry Smith for (k = 0; k < GMSH_NUM_POLYTOPES; ++k) keymap[k] = PETSC_INT_MIN;
12999566063dSJacob Faibussowitsch PetscCall(PetscMemzero(offset, sizeof(offset)));
13000598e1a2SLisandro Dalcin
1301066ea43fSLisandro Dalcin keymap[GMSH_TET] = nk++;
1302066ea43fSLisandro Dalcin keymap[GMSH_HEX] = nk++;
1303066ea43fSLisandro Dalcin keymap[GMSH_PRI] = nk++;
1304066ea43fSLisandro Dalcin keymap[GMSH_PYR] = nk++;
1305066ea43fSLisandro Dalcin keymap[GMSH_TRI] = nk++;
1306066ea43fSLisandro Dalcin keymap[GMSH_QUA] = nk++;
1307066ea43fSLisandro Dalcin keymap[GMSH_SEG] = nk++;
1308066ea43fSLisandro Dalcin keymap[GMSH_VTX] = nk++;
13090598e1a2SLisandro Dalcin
13109566063dSJacob Faibussowitsch PetscCall(GmshElementsCreate(mesh->numElems, &mesh->elements));
13114ad8454bSPierre Jolivet #define key(eid) keymap[GmshCellMap[elements[eid].cellType].polytope]
13120598e1a2SLisandro Dalcin for (e = 0; e < ne; ++e) offset[1 + key(e)]++;
13130598e1a2SLisandro Dalcin for (k = 1; k < nk; ++k) offset[k] += offset[k - 1];
13140598e1a2SLisandro Dalcin for (e = 0; e < ne; ++e) mesh->elements[offset[key(e)]++] = elements[e];
13150598e1a2SLisandro Dalcin #undef key
13169566063dSJacob Faibussowitsch PetscCall(GmshElementsDestroy(&elements));
1317066ea43fSLisandro Dalcin }
13180598e1a2SLisandro Dalcin
1319066ea43fSLisandro Dalcin { /* Mesh dimension and order */
1320066ea43fSLisandro Dalcin GmshElement *elem = mesh->numElems ? mesh->elements : NULL;
1321066ea43fSLisandro Dalcin mesh->dim = elem ? GmshCellMap[elem->cellType].dim : 0;
1322066ea43fSLisandro Dalcin mesh->order = elem ? GmshCellMap[elem->cellType].order : 0;
13230598e1a2SLisandro Dalcin }
13240598e1a2SLisandro Dalcin
13250598e1a2SLisandro Dalcin {
13260598e1a2SLisandro Dalcin PetscBT vtx;
13270598e1a2SLisandro Dalcin PetscInt dim = mesh->dim, e, n, v;
13280598e1a2SLisandro Dalcin
13299566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(mesh->numNodes, &vtx));
13300598e1a2SLisandro Dalcin
13310598e1a2SLisandro Dalcin /* Compute number of cells and set of vertices */
13320598e1a2SLisandro Dalcin mesh->numCells = 0;
13330598e1a2SLisandro Dalcin for (e = 0; e < mesh->numElems; ++e) {
13340598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + e;
13350598e1a2SLisandro Dalcin if (elem->dim == dim && dim > 0) mesh->numCells++;
133648a46eb9SPierre Jolivet for (v = 0; v < elem->numVerts; v++) PetscCall(PetscBTSet(vtx, elem->nodes[v]));
13370598e1a2SLisandro Dalcin }
13380598e1a2SLisandro Dalcin
13390598e1a2SLisandro Dalcin /* Compute numbering for vertices */
13400598e1a2SLisandro Dalcin mesh->numVerts = 0;
13419566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mesh->numNodes, &mesh->vertexMap));
13421690c2aeSBarry Smith for (n = 0; n < mesh->numNodes; ++n) mesh->vertexMap[n] = PetscBTLookup(vtx, n) ? mesh->numVerts++ : PETSC_INT_MIN;
13430598e1a2SLisandro Dalcin
13449566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&vtx));
13450598e1a2SLisandro Dalcin }
13463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
13470598e1a2SLisandro Dalcin }
13480598e1a2SLisandro Dalcin
GmshReadPeriodic(GmshFile * gmsh,GmshMesh * mesh)1349d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPeriodic(GmshFile *gmsh, GmshMesh *mesh)
1350d71ae5a4SJacob Faibussowitsch {
13510598e1a2SLisandro Dalcin PetscInt n;
13520598e1a2SLisandro Dalcin
13530598e1a2SLisandro Dalcin PetscFunctionBegin;
13549566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mesh->numNodes, &mesh->periodMap));
13550598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) mesh->periodMap[n] = n;
13560598e1a2SLisandro Dalcin switch (gmsh->fileFormat) {
1357d71ae5a4SJacob Faibussowitsch case 41:
1358d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadPeriodic_v41(gmsh, mesh->periodMap));
1359d71ae5a4SJacob Faibussowitsch break;
1360d71ae5a4SJacob Faibussowitsch default:
1361d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadPeriodic_v40(gmsh, mesh->periodMap));
1362d71ae5a4SJacob Faibussowitsch break;
13630598e1a2SLisandro Dalcin }
13640598e1a2SLisandro Dalcin
13659dddd249SSatish Balay /* Find canonical primary nodes */
13660598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n)
13679371c9d4SSatish Balay while (mesh->periodMap[n] != mesh->periodMap[mesh->periodMap[n]]) mesh->periodMap[n] = mesh->periodMap[mesh->periodMap[n]];
13680598e1a2SLisandro Dalcin
13699dddd249SSatish Balay /* Renumber vertices (filter out correspondings) */
13700598e1a2SLisandro Dalcin mesh->numVerts = 0;
13710598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n)
13720598e1a2SLisandro Dalcin if (mesh->vertexMap[n] >= 0) /* is vertex */
13739dddd249SSatish Balay if (mesh->periodMap[n] == n) /* is primary */
13740598e1a2SLisandro Dalcin mesh->vertexMap[n] = mesh->numVerts++;
13750598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n)
13760598e1a2SLisandro Dalcin if (mesh->vertexMap[n] >= 0) /* is vertex */
13779dddd249SSatish Balay if (mesh->periodMap[n] != n) /* is corresponding */
13780598e1a2SLisandro Dalcin mesh->vertexMap[n] = mesh->vertexMap[mesh->periodMap[n]];
13793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
13800598e1a2SLisandro Dalcin }
13810598e1a2SLisandro Dalcin
1382066ea43fSLisandro Dalcin #define DM_POLYTOPE_VERTEX DM_POLYTOPE_POINT
1383066ea43fSLisandro Dalcin static const DMPolytopeType DMPolytopeMap[] = {
1384066ea43fSLisandro Dalcin /* GMSH_VTX */ DM_POLYTOPE_VERTEX,
1385066ea43fSLisandro Dalcin /* GMSH_SEG */ DM_POLYTOPE_SEGMENT,
1386066ea43fSLisandro Dalcin /* GMSH_TRI */ DM_POLYTOPE_TRIANGLE,
1387066ea43fSLisandro Dalcin /* GMSH_QUA */ DM_POLYTOPE_QUADRILATERAL,
1388066ea43fSLisandro Dalcin /* GMSH_TET */ DM_POLYTOPE_TETRAHEDRON,
1389066ea43fSLisandro Dalcin /* GMSH_HEX */ DM_POLYTOPE_HEXAHEDRON,
1390066ea43fSLisandro Dalcin /* GMSH_PRI */ DM_POLYTOPE_TRI_PRISM,
13919371c9d4SSatish Balay /* GMSH_PYR */ DM_POLYTOPE_PYRAMID, DM_POLYTOPE_UNKNOWN};
13920598e1a2SLisandro Dalcin
DMPolytopeTypeFromGmsh(PetscInt cellType)1393d71ae5a4SJacob Faibussowitsch static inline DMPolytopeType DMPolytopeTypeFromGmsh(PetscInt cellType)
1394d71ae5a4SJacob Faibussowitsch {
1395066ea43fSLisandro Dalcin return DMPolytopeMap[GmshCellMap[cellType].polytope];
1396066ea43fSLisandro Dalcin }
1397066ea43fSLisandro Dalcin
GmshCreateFE(MPI_Comm comm,const char prefix[],PetscBool isSimplex,PetscBool continuity,PetscDTNodeType nodeType,PetscInt dim,PetscInt Nc,PetscInt k,PetscFE * fem)1398d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshCreateFE(MPI_Comm comm, const char prefix[], PetscBool isSimplex, PetscBool continuity, PetscDTNodeType nodeType, PetscInt dim, PetscInt Nc, PetscInt k, PetscFE *fem)
1399d71ae5a4SJacob Faibussowitsch {
1400066ea43fSLisandro Dalcin DM K;
1401066ea43fSLisandro Dalcin PetscSpace P;
1402066ea43fSLisandro Dalcin PetscDualSpace Q;
1403066ea43fSLisandro Dalcin PetscQuadrature q, fq;
1404066ea43fSLisandro Dalcin PetscBool isTensor = isSimplex ? PETSC_FALSE : PETSC_TRUE;
1405066ea43fSLisandro Dalcin PetscBool endpoint = PETSC_TRUE;
1406066ea43fSLisandro Dalcin char name[32];
1407066ea43fSLisandro Dalcin
1408066ea43fSLisandro Dalcin PetscFunctionBegin;
1409066ea43fSLisandro Dalcin /* Create space */
14109566063dSJacob Faibussowitsch PetscCall(PetscSpaceCreate(comm, &P));
14119566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetType(P, PETSCSPACEPOLYNOMIAL));
14129566063dSJacob Faibussowitsch PetscCall(PetscSpacePolynomialSetTensor(P, isTensor));
14139566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumComponents(P, Nc));
14149566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumVariables(P, dim));
14159566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetDegree(P, k, PETSC_DETERMINE));
1416066ea43fSLisandro Dalcin if (prefix) {
14179566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)P, prefix));
14189566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetFromOptions(P));
14199566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)P, NULL));
14209566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetDegree(P, &k, NULL));
1421066ea43fSLisandro Dalcin }
14229566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetUp(P));
1423066ea43fSLisandro Dalcin /* Create dual space */
14249566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceCreate(comm, &Q));
14259566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetType(Q, PETSCDUALSPACELAGRANGE));
14269566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceLagrangeSetTensor(Q, isTensor));
14279566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceLagrangeSetContinuity(Q, continuity));
14289566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceLagrangeSetNodeType(Q, nodeType, endpoint, 0));
14299566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetNumComponents(Q, Nc));
14309566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetOrder(Q, k));
14319566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell(PETSC_COMM_SELF, DMPolytopeTypeSimpleShape(dim, isSimplex), &K));
14329566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetDM(Q, K));
14339566063dSJacob Faibussowitsch PetscCall(DMDestroy(&K));
1434066ea43fSLisandro Dalcin if (prefix) {
14359566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)Q, prefix));
14369566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetFromOptions(Q));
14379566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)Q, NULL));
1438066ea43fSLisandro Dalcin }
14399566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetUp(Q));
1440066ea43fSLisandro Dalcin /* Create quadrature */
1441066ea43fSLisandro Dalcin if (isSimplex) {
14429566063dSJacob Faibussowitsch PetscCall(PetscDTStroudConicalQuadrature(dim, 1, k + 1, -1, +1, &q));
14439566063dSJacob Faibussowitsch PetscCall(PetscDTStroudConicalQuadrature(dim - 1, 1, k + 1, -1, +1, &fq));
1444066ea43fSLisandro Dalcin } else {
14459566063dSJacob Faibussowitsch PetscCall(PetscDTGaussTensorQuadrature(dim, 1, k + 1, -1, +1, &q));
14469566063dSJacob Faibussowitsch PetscCall(PetscDTGaussTensorQuadrature(dim - 1, 1, k + 1, -1, +1, &fq));
1447066ea43fSLisandro Dalcin }
1448066ea43fSLisandro Dalcin /* Create finite element */
14499566063dSJacob Faibussowitsch PetscCall(PetscFECreate(comm, fem));
14509566063dSJacob Faibussowitsch PetscCall(PetscFESetType(*fem, PETSCFEBASIC));
14519566063dSJacob Faibussowitsch PetscCall(PetscFESetNumComponents(*fem, Nc));
14529566063dSJacob Faibussowitsch PetscCall(PetscFESetBasisSpace(*fem, P));
14539566063dSJacob Faibussowitsch PetscCall(PetscFESetDualSpace(*fem, Q));
14549566063dSJacob Faibussowitsch PetscCall(PetscFESetQuadrature(*fem, q));
14559566063dSJacob Faibussowitsch PetscCall(PetscFESetFaceQuadrature(*fem, fq));
1456066ea43fSLisandro Dalcin if (prefix) {
14579566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*fem, prefix));
14589566063dSJacob Faibussowitsch PetscCall(PetscFESetFromOptions(*fem));
14599566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*fem, NULL));
1460066ea43fSLisandro Dalcin }
14619566063dSJacob Faibussowitsch PetscCall(PetscFESetUp(*fem));
1462066ea43fSLisandro Dalcin /* Cleanup */
14639566063dSJacob Faibussowitsch PetscCall(PetscSpaceDestroy(&P));
14649566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceDestroy(&Q));
14659566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&q));
14669566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&fq));
1467066ea43fSLisandro Dalcin /* Set finite element name */
146863a3b9bcSJacob Faibussowitsch PetscCall(PetscSNPrintf(name, sizeof(name), "%s%" PetscInt_FMT, isSimplex ? "P" : "Q", k));
14699566063dSJacob Faibussowitsch PetscCall(PetscFESetName(*fem, name));
14703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
147196ca5757SLisandro Dalcin }
147296ca5757SLisandro Dalcin
1473cc4c1da9SBarry Smith /*@
1474a1cb98faSBarry Smith DMPlexCreateGmshFromFile - Create a `DMPLEX` mesh from a Gmsh file
1475d6689ca9SLisandro Dalcin
1476a4e35b19SJacob Faibussowitsch Input Parameters:
1477d6689ca9SLisandro Dalcin + comm - The MPI communicator
1478d6689ca9SLisandro Dalcin . filename - Name of the Gmsh file
1479d6689ca9SLisandro Dalcin - interpolate - Create faces and edges in the mesh
1480d6689ca9SLisandro Dalcin
1481d6689ca9SLisandro Dalcin Output Parameter:
1482a1cb98faSBarry Smith . dm - The `DM` object representing the mesh
1483d6689ca9SLisandro Dalcin
1484d6689ca9SLisandro Dalcin Level: beginner
1485d6689ca9SLisandro Dalcin
14861cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()`
1487d6689ca9SLisandro Dalcin @*/
DMPlexCreateGmshFromFile(MPI_Comm comm,const char filename[],PetscBool interpolate,DM * dm)1488d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateGmshFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm)
1489d71ae5a4SJacob Faibussowitsch {
1490d6689ca9SLisandro Dalcin PetscViewer viewer;
1491d6689ca9SLisandro Dalcin PetscMPIInt rank;
1492d6689ca9SLisandro Dalcin int fileType;
1493d6689ca9SLisandro Dalcin PetscViewerType vtype;
1494d6689ca9SLisandro Dalcin
1495d6689ca9SLisandro Dalcin PetscFunctionBegin;
14969566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
1497d6689ca9SLisandro Dalcin
1498d6689ca9SLisandro Dalcin /* Determine Gmsh file type (ASCII or binary) from file header */
1499dd400576SPatrick Sanan if (rank == 0) {
15000598e1a2SLisandro Dalcin GmshFile gmsh[1];
1501d6689ca9SLisandro Dalcin char line[PETSC_MAX_PATH_LEN];
1502d6689ca9SLisandro Dalcin int snum;
1503d6689ca9SLisandro Dalcin float version;
1504a8d4e440SJunchao Zhang int fileFormat;
1505d6689ca9SLisandro Dalcin
15069566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(gmsh, 1));
15079566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(PETSC_COMM_SELF, &gmsh->viewer));
15089566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(gmsh->viewer, PETSCVIEWERASCII));
15099566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(gmsh->viewer, FILE_MODE_READ));
15109566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(gmsh->viewer, filename));
1511d6689ca9SLisandro Dalcin /* Read only the first two lines of the Gmsh file */
15129566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line));
15139566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$MeshFormat", line));
15149566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 2));
1515d6689ca9SLisandro Dalcin snum = sscanf(line, "%f %d", &version, &fileType);
1516a8d4e440SJunchao Zhang fileFormat = (int)roundf(version * 10);
151708401ef6SPierre Jolivet PetscCheck(snum == 2, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line);
1518a8d4e440SJunchao Zhang PetscCheck(fileFormat >= 22, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at least 2.2", (double)version);
15191dca8a05SBarry Smith PetscCheck((int)version != 3, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f not supported", (double)version);
1520a8d4e440SJunchao Zhang PetscCheck(fileFormat <= 41, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at most 4.1", (double)version);
15219566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&gmsh->viewer));
1522d6689ca9SLisandro Dalcin }
15239566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&fileType, 1, MPI_INT, 0, comm));
1524d6689ca9SLisandro Dalcin vtype = (fileType == 0) ? PETSCVIEWERASCII : PETSCVIEWERBINARY;
1525d6689ca9SLisandro Dalcin
1526d6689ca9SLisandro Dalcin /* Create appropriate viewer and build plex */
15279566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer));
15289566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, vtype));
15299566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
15309566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename));
15319566063dSJacob Faibussowitsch PetscCall(DMPlexCreateGmsh(comm, viewer, interpolate, dm));
15329566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer));
15333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1534d6689ca9SLisandro Dalcin }
1535d6689ca9SLisandro Dalcin
1536331830f3SMatthew G. Knepley /*@
1537a1cb98faSBarry Smith DMPlexCreateGmsh - Create a `DMPLEX` mesh from a Gmsh file viewer
1538331830f3SMatthew G. Knepley
1539d083f849SBarry Smith Collective
1540331830f3SMatthew G. Knepley
1541331830f3SMatthew G. Knepley Input Parameters:
1542331830f3SMatthew G. Knepley + comm - The MPI communicator
1543a1cb98faSBarry Smith . viewer - The `PetscViewer` associated with a Gmsh file
1544331830f3SMatthew G. Knepley - interpolate - Create faces and edges in the mesh
1545331830f3SMatthew G. Knepley
1546331830f3SMatthew G. Knepley Output Parameter:
1547a1cb98faSBarry Smith . dm - The `DM` object representing the mesh
1548331830f3SMatthew G. Knepley
1549a1cb98faSBarry Smith Options Database Keys:
1550df93260fSMatthew G. Knepley + -dm_plex_gmsh_hybrid - Force triangular prisms to use tensor order
1551df93260fSMatthew G. Knepley . -dm_plex_gmsh_periodic - Read Gmsh periodic section and construct a periodic Plex
1552df93260fSMatthew G. Knepley . -dm_plex_gmsh_highorder - Generate high-order coordinates
1553df93260fSMatthew 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
15542b205333SMatthew G. Knepley . -dm_plex_gmsh_use_generic - Generate generic labels, i.e. Cell Sets, Face Sets, etc.
1555df93260fSMatthew G. Knepley . -dm_plex_gmsh_use_regions - Generate labels with region names
1556df93260fSMatthew G. Knepley . -dm_plex_gmsh_mark_vertices - Add vertices to generated labels
15574c375d72SMatthew G. Knepley . -dm_plex_gmsh_mark_vertices_strict - Add vertices included in a region to generated labels
1558df93260fSMatthew G. Knepley . -dm_plex_gmsh_multiple_tags - Allow multiple tags for default labels
1559df93260fSMatthew G. Knepley - -dm_plex_gmsh_spacedim <d> - Embedding space dimension, if different from topological dimension
1560df93260fSMatthew G. Knepley
15611d27aa22SBarry Smith Level: beginner
15621d27aa22SBarry Smith
15631d27aa22SBarry Smith Notes:
15641d27aa22SBarry Smith The Gmsh file format is described in <http://gmsh.info/doc/texinfo/gmsh.html#MSH-file-format>
1565df93260fSMatthew G. Knepley
15666497c311SBarry Smith By default, the "Cell Sets", "Face Sets", and "Vertex Sets" labels are created, and only insert the first tag on a point. By using `-dm_plex_gmsh_multiple_tags`, all tags can be inserted. Alternatively, `-dm_plex_gmsh_use_regions` creates labels based on the region names from the `PhysicalNames` section, and all tags are used, but you can retain the generic labels using `-dm_plex_gmsh_use_generic`.
1567331830f3SMatthew G. Knepley
15681cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`
1569331830f3SMatthew G. Knepley @*/
DMPlexCreateGmsh(MPI_Comm comm,PetscViewer viewer,PetscBool interpolate,DM * dm)1570d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateGmsh(MPI_Comm comm, PetscViewer viewer, PetscBool interpolate, DM *dm)
1571d71ae5a4SJacob Faibussowitsch {
15720598e1a2SLisandro Dalcin GmshMesh *mesh = NULL;
157311c56cb0SLisandro Dalcin PetscViewer parentviewer = NULL;
15740598e1a2SLisandro Dalcin PetscBT periodicVerts = NULL;
1575eae3dc7dSJacob Faibussowitsch PetscBT *periodicCells = NULL;
15766858538eSMatthew G. Knepley DM cdm, cdmCell = NULL;
15776858538eSMatthew G. Knepley PetscSection cs, csCell = NULL;
15786858538eSMatthew G. Knepley Vec coordinates, coordinatesCell;
15790444adf6SMatthew G. Knepley DMLabel cellSets = NULL, faceSets = NULL, edgeSets = NULL, vertSets = NULL, marker = NULL, *regionSets;
15809db5b827SMatthew G. Knepley PetscInt dim = 0, coordDim = -1, order = 0, maxHeight = 0;
15819db5b827SMatthew G. Knepley PetscInt numNodes = 0, numElems = 0, numVerts = 0, numCells = 0, vStart, vEnd;
1582066ea43fSLisandro Dalcin PetscInt cell, cone[8], e, n, v, d;
15834c375d72SMatthew G. Knepley PetscBool usegeneric = PETSC_TRUE, useregions = PETSC_FALSE, markvertices = PETSC_FALSE, markverticesstrict = PETSC_FALSE, multipleTags = PETSC_FALSE;
15842b205333SMatthew G. Knepley PetscBool flg, binary, hybrid = interpolate, periodic = PETSC_TRUE;
1585066ea43fSLisandro Dalcin PetscBool highOrder = PETSC_TRUE, highOrderSet, project = PETSC_FALSE;
1586066ea43fSLisandro Dalcin PetscBool isSimplex = PETSC_FALSE, isHybrid = PETSC_FALSE, hasTetra = PETSC_FALSE;
15870598e1a2SLisandro Dalcin PetscMPIInt rank;
1588331830f3SMatthew G. Knepley
1589331830f3SMatthew G. Knepley PetscFunctionBegin;
15909566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
1591d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)viewer);
1592d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Gmsh options");
1593df93260fSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_gmsh_hybrid", "Force triangular prisms to use tensor order", "DMPlexCreateGmsh", hybrid, &hybrid, NULL));
15949566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_periodic", "Read Gmsh periodic section", "DMPlexCreateGmsh", periodic, &periodic, NULL));
15959566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_highorder", "Generate high-order coordinates", "DMPlexCreateGmsh", highOrder, &highOrder, &highOrderSet));
15969566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_project", "Project high-order coordinates to a different space", "DMPlexCreateGmsh", project, &project, NULL));
15979566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_use_regions", "Generate labels with region names", "DMPlexCreateGmsh", useregions, &useregions, NULL));
15982b205333SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_gmsh_use_generic", "Generate generic labels, i.e. Cell Sets, Face Sets, etc", "DMPlexCreateGmsh", usegeneric, &usegeneric, &flg));
15992b205333SMatthew G. Knepley if (!flg && useregions) usegeneric = PETSC_FALSE;
16009566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_mark_vertices", "Add vertices to generated labels", "DMPlexCreateGmsh", markvertices, &markvertices, NULL));
16014c375d72SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_gmsh_mark_vertices_strict", "Add only directly tagged vertices to generated labels", "DMPlexCreateGmsh", markverticesstrict, &markverticesstrict, NULL));
1602df93260fSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_gmsh_multiple_tags", "Allow multiple tags for default labels", "DMPlexCreateGmsh", multipleTags, &multipleTags, NULL));
16039566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_gmsh_spacedim", "Embedding space dimension", "DMPlexCreateGmsh", coordDim, &coordDim, NULL, PETSC_DECIDE));
16049db5b827SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_localize_height", "Localize edges and faces in addition to cells", "", maxHeight, &maxHeight, NULL, 0));
1605d0609cedSBarry Smith PetscOptionsHeadEnd();
1606d0609cedSBarry Smith PetscOptionsEnd();
16070598e1a2SLisandro Dalcin
16089566063dSJacob Faibussowitsch PetscCall(GmshCellInfoSetUp());
160911c56cb0SLisandro Dalcin
16109566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm));
16119566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX));
16129566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CreateGmsh, *dm, NULL, NULL, NULL));
161311c56cb0SLisandro Dalcin
16149566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &binary));
161511c56cb0SLisandro Dalcin
161611c56cb0SLisandro Dalcin /* Binary viewers read on all ranks, get subviewer to read only in rank 0 */
16173b46f529SLisandro Dalcin if (binary) {
161811c56cb0SLisandro Dalcin parentviewer = viewer;
16199566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(parentviewer, PETSC_COMM_SELF, &viewer));
162011c56cb0SLisandro Dalcin }
162111c56cb0SLisandro Dalcin
1622dd400576SPatrick Sanan if (rank == 0) {
16230598e1a2SLisandro Dalcin GmshFile gmsh[1];
1624698a79b9SLisandro Dalcin char line[PETSC_MAX_PATH_LEN];
1625698a79b9SLisandro Dalcin PetscBool match;
1626331830f3SMatthew G. Knepley
16279566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(gmsh, 1));
1628698a79b9SLisandro Dalcin gmsh->viewer = viewer;
1629698a79b9SLisandro Dalcin gmsh->binary = binary;
1630698a79b9SLisandro Dalcin
16319566063dSJacob Faibussowitsch PetscCall(GmshMeshCreate(&mesh));
16320598e1a2SLisandro Dalcin
1633698a79b9SLisandro Dalcin /* Read mesh format */
16349566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line));
16359566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$MeshFormat", line));
16369566063dSJacob Faibussowitsch PetscCall(GmshReadMeshFormat(gmsh));
16379566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndMeshFormat", line));
163811c56cb0SLisandro Dalcin
16398749820aSMatthew G. Knepley /* OPTIONAL Read mesh version (Neper only) */
16409566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line));
16418749820aSMatthew G. Knepley PetscCall(GmshMatch(gmsh, "$MeshVersion", line, &match));
16428749820aSMatthew G. Knepley if (match) {
16438749820aSMatthew G. Knepley PetscCall(GmshExpect(gmsh, "$MeshVersion", line));
16448749820aSMatthew G. Knepley PetscCall(GmshReadMeshVersion(gmsh));
16458749820aSMatthew G. Knepley PetscCall(GmshReadEndSection(gmsh, "$EndMeshVersion", line));
16468749820aSMatthew G. Knepley /* Initial read for entity section */
16478749820aSMatthew G. Knepley PetscCall(GmshReadSection(gmsh, line));
16488749820aSMatthew G. Knepley }
16498749820aSMatthew G. Knepley
16508749820aSMatthew G. Knepley /* OPTIONAL Read mesh domain (Neper only) */
16518749820aSMatthew G. Knepley PetscCall(GmshMatch(gmsh, "$Domain", line, &match));
16528749820aSMatthew G. Knepley if (match) {
16538749820aSMatthew G. Knepley PetscCall(GmshExpect(gmsh, "$Domain", line));
16548749820aSMatthew G. Knepley PetscCall(GmshReadMeshDomain(gmsh));
16558749820aSMatthew G. Knepley PetscCall(GmshReadEndSection(gmsh, "$EndDomain", line));
16568749820aSMatthew G. Knepley /* Initial read for entity section */
16578749820aSMatthew G. Knepley PetscCall(GmshReadSection(gmsh, line));
16588749820aSMatthew G. Knepley }
16598749820aSMatthew G. Knepley
16608749820aSMatthew G. Knepley /* OPTIONAL Read physical names */
16619566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, "$PhysicalNames", line, &match));
1662dc0ede3bSMatthew G. Knepley if (match) {
16639566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$PhysicalNames", line));
16649566063dSJacob Faibussowitsch PetscCall(GmshReadPhysicalNames(gmsh, mesh));
16659566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndPhysicalNames", line));
1666698a79b9SLisandro Dalcin /* Initial read for entity section */
16679566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line));
1668dc0ede3bSMatthew G. Knepley }
166911c56cb0SLisandro Dalcin
1670e43c9757SMatthew G. Knepley /* OPTIONAL Read entities */
1671698a79b9SLisandro Dalcin if (gmsh->fileFormat >= 40) {
1672e43c9757SMatthew G. Knepley PetscCall(GmshMatch(gmsh, "$Entities", line, &match));
1673e43c9757SMatthew G. Knepley if (match) {
16749566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$Entities", line));
16759566063dSJacob Faibussowitsch PetscCall(GmshReadEntities(gmsh, mesh));
16769566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndEntities", line));
1677698a79b9SLisandro Dalcin /* Initial read for nodes section */
16789566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line));
1679de78e4feSLisandro Dalcin }
1680e43c9757SMatthew G. Knepley }
1681de78e4feSLisandro Dalcin
1682698a79b9SLisandro Dalcin /* Read nodes */
16839566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$Nodes", line));
16849566063dSJacob Faibussowitsch PetscCall(GmshReadNodes(gmsh, mesh));
16859566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndNodes", line));
168611c56cb0SLisandro Dalcin
1687698a79b9SLisandro Dalcin /* Read elements */
16889566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line));
16899566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$Elements", line));
16909566063dSJacob Faibussowitsch PetscCall(GmshReadElements(gmsh, mesh));
16919566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndElements", line));
1692de78e4feSLisandro Dalcin
16930598e1a2SLisandro Dalcin /* Read periodic section (OPTIONAL) */
1694698a79b9SLisandro Dalcin if (periodic) {
16959566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line));
16969566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, "$Periodic", line, &periodic));
1697ef12879bSLisandro Dalcin }
1698ef12879bSLisandro Dalcin if (periodic) {
16999566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$Periodic", line));
17009566063dSJacob Faibussowitsch PetscCall(GmshReadPeriodic(gmsh, mesh));
17019566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndPeriodic", line));
1702698a79b9SLisandro Dalcin }
1703698a79b9SLisandro Dalcin
17049566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->wbuf));
17059566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->sbuf));
17069566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->nbuf));
17070598e1a2SLisandro Dalcin
17080598e1a2SLisandro Dalcin dim = mesh->dim;
1709066ea43fSLisandro Dalcin order = mesh->order;
17100598e1a2SLisandro Dalcin numNodes = mesh->numNodes;
17110598e1a2SLisandro Dalcin numElems = mesh->numElems;
17120598e1a2SLisandro Dalcin numVerts = mesh->numVerts;
17130598e1a2SLisandro Dalcin numCells = mesh->numCells;
1714066ea43fSLisandro Dalcin
1715066ea43fSLisandro Dalcin {
1716066ea43fSLisandro Dalcin GmshElement *elemA = mesh->numCells > 0 ? mesh->elements : NULL;
17178e3a54c0SPierre Jolivet GmshElement *elemB = PetscSafePointerPlusOffset(elemA, mesh->numCells - 1);
1718066ea43fSLisandro Dalcin int ptA = elemA ? GmshCellMap[elemA->cellType].polytope : -1;
1719066ea43fSLisandro Dalcin int ptB = elemB ? GmshCellMap[elemB->cellType].polytope : -1;
1720066ea43fSLisandro Dalcin isSimplex = (ptA == GMSH_QUA || ptA == GMSH_HEX) ? PETSC_FALSE : PETSC_TRUE;
1721066ea43fSLisandro Dalcin isHybrid = (ptA == ptB) ? PETSC_FALSE : PETSC_TRUE;
1722066ea43fSLisandro Dalcin hasTetra = (ptA == GMSH_TET) ? PETSC_TRUE : PETSC_FALSE;
1723066ea43fSLisandro Dalcin }
1724698a79b9SLisandro Dalcin }
1725698a79b9SLisandro Dalcin
172648a46eb9SPierre Jolivet if (parentviewer) PetscCall(PetscViewerRestoreSubViewer(parentviewer, PETSC_COMM_SELF, &viewer));
1727698a79b9SLisandro Dalcin
1728066ea43fSLisandro Dalcin {
1729066ea43fSLisandro Dalcin int buf[6];
1730698a79b9SLisandro Dalcin
1731066ea43fSLisandro Dalcin buf[0] = (int)dim;
1732066ea43fSLisandro Dalcin buf[1] = (int)order;
1733066ea43fSLisandro Dalcin buf[2] = periodic;
1734066ea43fSLisandro Dalcin buf[3] = isSimplex;
1735066ea43fSLisandro Dalcin buf[4] = isHybrid;
1736066ea43fSLisandro Dalcin buf[5] = hasTetra;
1737066ea43fSLisandro Dalcin
17389566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(buf, 6, MPI_INT, 0, comm));
1739066ea43fSLisandro Dalcin
1740066ea43fSLisandro Dalcin dim = buf[0];
1741066ea43fSLisandro Dalcin order = buf[1];
1742066ea43fSLisandro Dalcin periodic = buf[2] ? PETSC_TRUE : PETSC_FALSE;
1743066ea43fSLisandro Dalcin isSimplex = buf[3] ? PETSC_TRUE : PETSC_FALSE;
1744066ea43fSLisandro Dalcin isHybrid = buf[4] ? PETSC_TRUE : PETSC_FALSE;
1745066ea43fSLisandro Dalcin hasTetra = buf[5] ? PETSC_TRUE : PETSC_FALSE;
1746dea2a3c7SStefano Zampini }
1747dea2a3c7SStefano Zampini
1748066ea43fSLisandro Dalcin if (!highOrderSet) highOrder = (order > 1) ? PETSC_TRUE : PETSC_FALSE;
174908401ef6SPierre Jolivet PetscCheck(!highOrder || !isHybrid, comm, PETSC_ERR_SUP, "No support for discretization on hybrid meshes yet");
1750066ea43fSLisandro Dalcin
17510598e1a2SLisandro Dalcin /* We do not want this label automatically computed, instead we fill it here */
17529566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "celltype"));
175311c56cb0SLisandro Dalcin
1754a4bb7517SMichael Lange /* Allocate the cell-vertex mesh */
17559566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(*dm, 0, numCells + numVerts));
17560598e1a2SLisandro Dalcin for (cell = 0; cell < numCells; ++cell) {
17570598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + cell;
17580598e1a2SLisandro Dalcin DMPolytopeType ctype = DMPolytopeTypeFromGmsh(elem->cellType);
17590598e1a2SLisandro Dalcin if (hybrid && hasTetra && ctype == DM_POLYTOPE_TRI_PRISM) ctype = DM_POLYTOPE_TRI_PRISM_TENSOR;
17609566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(*dm, cell, elem->numVerts));
17619566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(*dm, cell, ctype));
1762db397164SMichael Lange }
176348a46eb9SPierre Jolivet for (v = numCells; v < numCells + numVerts; ++v) PetscCall(DMPlexSetCellType(*dm, v, DM_POLYTOPE_POINT));
17649566063dSJacob Faibussowitsch PetscCall(DMSetUp(*dm));
176596ca5757SLisandro Dalcin
1766a4bb7517SMichael Lange /* Add cell-vertex connections */
17670598e1a2SLisandro Dalcin for (cell = 0; cell < numCells; ++cell) {
17680598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + cell;
17690598e1a2SLisandro Dalcin for (v = 0; v < elem->numVerts; ++v) {
17700598e1a2SLisandro Dalcin const PetscInt nn = elem->nodes[v];
17710598e1a2SLisandro Dalcin const PetscInt vv = mesh->vertexMap[nn];
17720598e1a2SLisandro Dalcin cone[v] = numCells + vv;
1773db397164SMichael Lange }
17749566063dSJacob Faibussowitsch PetscCall(DMPlexReorderCell(*dm, cell, cone));
17759566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(*dm, cell, cone));
1776a4bb7517SMichael Lange }
177796ca5757SLisandro Dalcin
17789566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim));
17799566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(*dm));
17809566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(*dm));
1781331830f3SMatthew G. Knepley if (interpolate) {
17825fd9971aSMatthew G. Knepley DM idm;
1783331830f3SMatthew G. Knepley
17849566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm));
17859566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm));
1786331830f3SMatthew G. Knepley *dm = idm;
1787331830f3SMatthew G. Knepley }
17889db5b827SMatthew G. Knepley PetscCall(DMPlexGetDepthStratum(*dm, 0, &vStart, &vEnd));
1789917266a4SLisandro Dalcin
1790dd400576SPatrick Sanan if (rank == 0) {
1791a45dabc8SMatthew G. Knepley const PetscInt Nr = useregions ? mesh->numRegions : 0;
1792d1a54cefSMatthew G. Knepley
17939566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(Nr, ®ionSets));
17940598e1a2SLisandro Dalcin for (cell = 0, e = 0; e < numElems; ++e) {
17950598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + e;
17966e1dd89aSLawrence Mitchell
17976e1dd89aSLawrence Mitchell /* Create cell sets */
17980598e1a2SLisandro Dalcin if (elem->dim == dim && dim > 0) {
17990598e1a2SLisandro Dalcin if (elem->numTags > 0) {
1800df93260fSMatthew G. Knepley PetscInt Nt = elem->numTags, t, r;
1801a45dabc8SMatthew G. Knepley
1802df93260fSMatthew G. Knepley for (t = 0; t < Nt; ++t) {
1803df93260fSMatthew G. Knepley const PetscInt tag = elem->tags[t];
18042b205333SMatthew G. Knepley const PetscBool generic = usegeneric && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE;
1805df93260fSMatthew G. Knepley
1806df93260fSMatthew G. Knepley if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &cellSets, "Cell Sets", cell, tag));
1807a45dabc8SMatthew G. Knepley for (r = 0; r < Nr; ++r) {
1808df93260fSMatthew G. Knepley if (mesh->regionDims[r] != dim) continue;
18099566063dSJacob Faibussowitsch if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], cell, tag));
1810a45dabc8SMatthew G. Knepley }
18116e1dd89aSLawrence Mitchell }
1812df93260fSMatthew G. Knepley }
1813917266a4SLisandro Dalcin cell++;
18146e1dd89aSLawrence Mitchell }
18150c070f12SSander Arens
18160598e1a2SLisandro Dalcin /* Create face sets */
1817aec57b10SMatthew G. Knepley if (elem->numTags && interpolate && elem->dim == dim - 1) {
18180598e1a2SLisandro Dalcin PetscInt joinSize;
18190598e1a2SLisandro Dalcin const PetscInt *join = NULL;
18200444adf6SMatthew G. Knepley PetscInt Nt = elem->numTags, pdepth;
1821a45dabc8SMatthew G. Knepley
18220598e1a2SLisandro Dalcin /* Find the relevant facet with vertex joins */
18230598e1a2SLisandro Dalcin for (v = 0; v < elem->numVerts; ++v) {
18240598e1a2SLisandro Dalcin const PetscInt nn = elem->nodes[v];
18250598e1a2SLisandro Dalcin const PetscInt vv = mesh->vertexMap[nn];
18260598e1a2SLisandro Dalcin cone[v] = vStart + vv;
18270598e1a2SLisandro Dalcin }
18289566063dSJacob Faibussowitsch PetscCall(DMPlexGetFullJoin(*dm, elem->numVerts, cone, &joinSize, &join));
182963a3b9bcSJacob 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);
18300444adf6SMatthew G. Knepley PetscCall(DMPlexGetPointDepth(*dm, join[0], &pdepth));
18310444adf6SMatthew G. Knepley PetscCheck(pdepth == dim - 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Plex facet %" PetscInt_FMT " for Gmsh element %" PetscInt_FMT " had depth %" PetscInt_FMT " != %" PetscInt_FMT, join[0], elem->id, pdepth, dim - 1);
18320444adf6SMatthew G. Knepley for (PetscInt t = 0; t < Nt; ++t) {
18335ad74b4fSMatthew G. Knepley const PetscInt tag = elem->tags[t];
18342b205333SMatthew G. Knepley const PetscBool generic = usegeneric && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE;
18355ad74b4fSMatthew G. Knepley
1836df93260fSMatthew G. Knepley if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &faceSets, "Face Sets", join[0], tag));
18370444adf6SMatthew G. Knepley for (PetscInt r = 0; r < Nr; ++r) {
1838df93260fSMatthew G. Knepley if (mesh->regionDims[r] != dim - 1) continue;
18399566063dSJacob Faibussowitsch if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], join[0], tag));
1840a45dabc8SMatthew G. Knepley }
18415ad74b4fSMatthew G. Knepley }
18429566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(*dm, elem->numVerts, cone, &joinSize, &join));
18430598e1a2SLisandro Dalcin }
18440598e1a2SLisandro Dalcin
1845aec57b10SMatthew G. Knepley /* Create edge sets */
1846aec57b10SMatthew G. Knepley if (elem->numTags && interpolate && dim > 2 && elem->dim == 1) {
1847aec57b10SMatthew G. Knepley PetscInt joinSize;
1848aec57b10SMatthew G. Knepley const PetscInt *join = NULL;
1849aec57b10SMatthew G. Knepley PetscInt Nt = elem->numTags, t, r;
1850aec57b10SMatthew G. Knepley
1851aec57b10SMatthew G. Knepley /* Find the relevant edge with vertex joins */
1852aec57b10SMatthew G. Knepley for (v = 0; v < elem->numVerts; ++v) {
1853aec57b10SMatthew G. Knepley const PetscInt nn = elem->nodes[v];
1854aec57b10SMatthew G. Knepley const PetscInt vv = mesh->vertexMap[nn];
1855aec57b10SMatthew G. Knepley cone[v] = vStart + vv;
1856aec57b10SMatthew G. Knepley }
1857aec57b10SMatthew G. Knepley PetscCall(DMPlexGetJoin(*dm, elem->numVerts, cone, &joinSize, &join));
1858aec57b10SMatthew G. Knepley PetscCheck(joinSize == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Could not determine Plex edge for Gmsh element %" PetscInt_FMT " (Plex cell %" PetscInt_FMT ")", elem->id, e);
1859aec57b10SMatthew G. Knepley for (t = 0; t < Nt; ++t) {
1860aec57b10SMatthew G. Knepley const PetscInt tag = elem->tags[t];
18612b205333SMatthew G. Knepley const PetscBool generic = usegeneric && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE;
1862aec57b10SMatthew G. Knepley
18630444adf6SMatthew G. Knepley if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &edgeSets, "Edge Sets", join[0], tag));
1864aec57b10SMatthew G. Knepley for (r = 0; r < Nr; ++r) {
1865aec57b10SMatthew G. Knepley if (mesh->regionDims[r] != 1) continue;
1866aec57b10SMatthew G. Knepley if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], join[0], tag));
1867aec57b10SMatthew G. Knepley }
1868aec57b10SMatthew G. Knepley }
1869aec57b10SMatthew G. Knepley PetscCall(DMPlexRestoreJoin(*dm, elem->numVerts, cone, &joinSize, &join));
1870aec57b10SMatthew G. Knepley }
1871aec57b10SMatthew G. Knepley
18720c070f12SSander Arens /* Create vertex sets */
18734c375d72SMatthew G. Knepley if (elem->numTags && elem->dim == 0 && (markverticesstrict || markvertices)) {
18740598e1a2SLisandro Dalcin const PetscInt nn = elem->nodes[0];
18750598e1a2SLisandro Dalcin const PetscInt vv = mesh->vertexMap[nn];
1876bb3f7942SBrad Aagaard PetscInt Nt = elem->numTags;
1877bb3f7942SBrad Aagaard
1878bb3f7942SBrad Aagaard for (PetscInt t = 0; t < Nt; ++t) {
1879bb3f7942SBrad Aagaard const PetscInt tag = elem->tags[t];
1880a45dabc8SMatthew G. Knepley
18818a3d9825SMatthew G. Knepley if (vv < 0) continue;
18822b205333SMatthew G. Knepley if (usegeneric) PetscCall(DMSetLabelValue_Fast(*dm, &vertSets, "Vertex Sets", vStart + vv, tag));
1883bb3f7942SBrad Aagaard for (PetscInt r = 0; r < Nr; ++r) {
1884df93260fSMatthew G. Knepley if (mesh->regionDims[r] != 0) continue;
18859566063dSJacob Faibussowitsch if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], vStart + vv, tag));
188681a1af93SMatthew G. Knepley }
188781a1af93SMatthew G. Knepley }
188881a1af93SMatthew G. Knepley }
1889bb3f7942SBrad Aagaard }
189081a1af93SMatthew G. Knepley if (markvertices) {
189181a1af93SMatthew G. Knepley for (v = 0; v < numNodes; ++v) {
189281a1af93SMatthew G. Knepley const PetscInt vv = mesh->vertexMap[v];
18937d5b9244SMatthew G. Knepley const PetscInt *tags = &mesh->nodelist->tag[v * GMSH_MAX_TAGS];
18947d5b9244SMatthew G. Knepley PetscInt r, t;
189581a1af93SMatthew G. Knepley
18968a3d9825SMatthew G. Knepley if (vv < 0) continue;
18977d5b9244SMatthew G. Knepley for (t = 0; t < GMSH_MAX_TAGS; ++t) {
18987d5b9244SMatthew G. Knepley const PetscInt tag = tags[t];
18992b205333SMatthew G. Knepley const PetscBool generic = usegeneric && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE;
19007d5b9244SMatthew G. Knepley
19017d5b9244SMatthew G. Knepley if (tag == -1) continue;
1902df93260fSMatthew G. Knepley if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &vertSets, "Vertex Sets", vStart + vv, tag));
1903a45dabc8SMatthew G. Knepley for (r = 0; r < Nr; ++r) {
19049566063dSJacob Faibussowitsch if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], vStart + vv, tag));
19050598e1a2SLisandro Dalcin }
19060598e1a2SLisandro Dalcin }
19070598e1a2SLisandro Dalcin }
19080598e1a2SLisandro Dalcin }
19099566063dSJacob Faibussowitsch PetscCall(PetscFree(regionSets));
1910a45dabc8SMatthew G. Knepley }
19110598e1a2SLisandro Dalcin
19120444adf6SMatthew G. Knepley { /* Create Cell/Face/Edge/Vertex Sets labels at all processes */
19139371c9d4SSatish Balay enum {
19140444adf6SMatthew G. Knepley n = 5
19159371c9d4SSatish Balay };
19167dd454faSLisandro Dalcin PetscBool flag[n];
19177dd454faSLisandro Dalcin
19187dd454faSLisandro Dalcin flag[0] = cellSets ? PETSC_TRUE : PETSC_FALSE;
19197dd454faSLisandro Dalcin flag[1] = faceSets ? PETSC_TRUE : PETSC_FALSE;
19200444adf6SMatthew G. Knepley flag[2] = edgeSets ? PETSC_TRUE : PETSC_FALSE;
19210444adf6SMatthew G. Knepley flag[3] = vertSets ? PETSC_TRUE : PETSC_FALSE;
19220444adf6SMatthew G. Knepley flag[4] = marker ? PETSC_TRUE : PETSC_FALSE;
1923*5440e5dcSBarry Smith PetscCallMPI(MPI_Bcast(flag, n, MPI_C_BOOL, 0, comm));
19249566063dSJacob Faibussowitsch if (flag[0]) PetscCall(DMCreateLabel(*dm, "Cell Sets"));
19259566063dSJacob Faibussowitsch if (flag[1]) PetscCall(DMCreateLabel(*dm, "Face Sets"));
19260444adf6SMatthew G. Knepley if (flag[2]) PetscCall(DMCreateLabel(*dm, "Edge Sets"));
19270444adf6SMatthew G. Knepley if (flag[3]) PetscCall(DMCreateLabel(*dm, "Vertex Sets"));
19280444adf6SMatthew G. Knepley if (flag[4]) PetscCall(DMCreateLabel(*dm, "marker"));
19297dd454faSLisandro Dalcin }
19307dd454faSLisandro Dalcin
19310598e1a2SLisandro Dalcin if (periodic) {
19329566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(numVerts, &periodicVerts));
19330598e1a2SLisandro Dalcin for (n = 0; n < numNodes; ++n) {
19340598e1a2SLisandro Dalcin if (mesh->vertexMap[n] >= 0) {
19350598e1a2SLisandro Dalcin if (PetscUnlikely(mesh->periodMap[n] != n)) {
19360598e1a2SLisandro Dalcin PetscInt m = mesh->periodMap[n];
19379566063dSJacob Faibussowitsch PetscCall(PetscBTSet(periodicVerts, mesh->vertexMap[n]));
19389566063dSJacob Faibussowitsch PetscCall(PetscBTSet(periodicVerts, mesh->vertexMap[m]));
19390598e1a2SLisandro Dalcin }
19400598e1a2SLisandro Dalcin }
19410598e1a2SLisandro Dalcin }
19429db5b827SMatthew G. Knepley PetscCall(DMGetCoordinateDM(*dm, &cdm));
1943eae3dc7dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxHeight + 1, &periodicCells));
19449db5b827SMatthew G. Knepley for (PetscInt h = 0; h <= maxHeight; ++h) {
19459db5b827SMatthew G. Knepley PetscInt pStart, pEnd;
19469db5b827SMatthew G. Knepley
19479db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(*dm, h, &pStart, &pEnd));
19489db5b827SMatthew G. Knepley PetscCall(PetscBTCreate(pEnd - pStart, &periodicCells[h]));
19499db5b827SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) {
19509db5b827SMatthew G. Knepley PetscInt *closure = NULL;
19519db5b827SMatthew G. Knepley PetscInt Ncl;
19529db5b827SMatthew G. Knepley
19539db5b827SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure));
19549db5b827SMatthew G. Knepley for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) {
19559db5b827SMatthew G. Knepley if (closure[cl] >= vStart && closure[cl] < vEnd) {
19569db5b827SMatthew G. Knepley if (PetscUnlikely(PetscBTLookup(periodicVerts, closure[cl] - vStart))) {
19579db5b827SMatthew G. Knepley PetscCall(PetscBTSet(periodicCells[h], p - pStart));
19589371c9d4SSatish Balay break;
19590c070f12SSander Arens }
19600c070f12SSander Arens }
19610c070f12SSander Arens }
19629db5b827SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure));
19639db5b827SMatthew G. Knepley }
19649db5b827SMatthew G. Knepley }
196516ad7e67SMichael Lange }
196616ad7e67SMichael Lange
1967066ea43fSLisandro Dalcin /* Setup coordinate DM */
19680598e1a2SLisandro Dalcin if (coordDim < 0) coordDim = dim;
19699566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(*dm, coordDim));
19709566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(*dm, &cdm));
1971066ea43fSLisandro Dalcin if (highOrder) {
1972066ea43fSLisandro Dalcin PetscFE fe;
1973066ea43fSLisandro Dalcin PetscBool continuity = periodic ? PETSC_FALSE : PETSC_TRUE;
1974066ea43fSLisandro Dalcin PetscDTNodeType nodeType = PETSCDTNODES_EQUISPACED;
1975066ea43fSLisandro Dalcin
1976066ea43fSLisandro Dalcin if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */
1977066ea43fSLisandro Dalcin
19789566063dSJacob Faibussowitsch PetscCall(GmshCreateFE(comm, NULL, isSimplex, continuity, nodeType, dim, coordDim, order, &fe));
19799566063dSJacob Faibussowitsch PetscCall(PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_fe_view"));
19809566063dSJacob Faibussowitsch PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)fe));
19819566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe));
19829566063dSJacob Faibussowitsch PetscCall(DMCreateDS(cdm));
1983066ea43fSLisandro Dalcin }
19846858538eSMatthew G. Knepley if (periodic) {
19856858538eSMatthew G. Knepley PetscCall(DMClone(cdm, &cdmCell));
19866858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(*dm, cdmCell));
19876858538eSMatthew G. Knepley }
1988066ea43fSLisandro Dalcin
1989066ea43fSLisandro Dalcin /* Create coordinates */
1990066ea43fSLisandro Dalcin if (highOrder) {
1991066ea43fSLisandro Dalcin PetscInt maxDof = GmshNumNodes_HEX(order) * coordDim;
1992066ea43fSLisandro Dalcin double *coords = mesh ? mesh->nodelist->xyz : NULL;
1993066ea43fSLisandro Dalcin PetscSection section;
1994066ea43fSLisandro Dalcin PetscScalar *cellCoords;
1995066ea43fSLisandro Dalcin
19969566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(cdm, NULL));
19976858538eSMatthew G. Knepley PetscCall(DMGetLocalSection(cdm, &cs));
19986858538eSMatthew G. Knepley PetscCall(PetscSectionClone(cs, §ion));
19999566063dSJacob Faibussowitsch PetscCall(DMPlexSetClosurePermutationTensor(cdm, 0, section)); /* XXX Implement DMPlexSetClosurePermutationLexicographic() */
2000066ea43fSLisandro Dalcin
20019566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(cdm, &coordinates));
20029566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof, &cellCoords));
2003066ea43fSLisandro Dalcin for (cell = 0; cell < numCells; ++cell) {
2004066ea43fSLisandro Dalcin GmshElement *elem = mesh->elements + cell;
2005066ea43fSLisandro Dalcin const int *lexorder = GmshCellMap[elem->cellType].lexorder();
2006b9bf55e5SMatthew G. Knepley int s = 0;
2007066ea43fSLisandro Dalcin for (n = 0; n < elem->numNodes; ++n) {
2008b9bf55e5SMatthew G. Knepley while (lexorder[n + s] < 0) ++s;
2009b9bf55e5SMatthew G. Knepley const PetscInt node = elem->nodes[lexorder[n + s]];
2010b9bf55e5SMatthew G. Knepley for (d = 0; d < coordDim; ++d) cellCoords[(n + s) * coordDim + d] = (PetscReal)coords[node * 3 + d];
2011b9bf55e5SMatthew G. Knepley }
2012b9bf55e5SMatthew G. Knepley if (s) {
2013b9bf55e5SMatthew G. Knepley /* For the coordinate mapping we weight vertices by -1/4 and edges by 1/2, which we get from Q_2 interpolation */
2014b9bf55e5SMatthew G. Knepley PetscReal quaCenterWeights[9] = {-0.25, 0.5, -0.25, 0.5, 0.0, 0.5, -0.25, 0.5, -0.25};
2015b9bf55e5SMatthew G. Knepley /* For the coordinate mapping we weight vertices by -1/4 and edges by 1/2, which we get from Q_2 interpolation */
20169371c9d4SSatish 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};
20179371c9d4SSatish 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};
20189371c9d4SSatish 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};
20199371c9d4SSatish 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};
20209371c9d4SSatish 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};
20219371c9d4SSatish 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};
20229371c9d4SSatish 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};
2023b9bf55e5SMatthew G. Knepley PetscReal *sdWeights2[9] = {NULL, NULL, NULL, NULL, quaCenterWeights, NULL, NULL, NULL, NULL};
20249371c9d4SSatish Balay PetscReal *sdWeights3[27] = {NULL, NULL, NULL, NULL, hexBottomWeights, NULL, NULL, NULL, NULL, NULL, hexFrontWeights, NULL, hexLeftWeights, hexCenterWeights, hexRightWeights, NULL, hexBackWeights, NULL,
2025b9bf55e5SMatthew G. Knepley NULL, NULL, NULL, NULL, hexTopWeights, NULL, NULL, NULL, NULL};
2026b9bf55e5SMatthew G. Knepley PetscReal **sdWeights[4] = {NULL, NULL, sdWeights2, sdWeights3};
2027b9bf55e5SMatthew G. Knepley
2028b9bf55e5SMatthew G. Knepley /* Missing entries in serendipity cell, only works for 8-node quad and 20-node hex */
2029b9bf55e5SMatthew G. Knepley for (n = 0; n < elem->numNodes + s; ++n) {
2030b9bf55e5SMatthew G. Knepley if (lexorder[n] >= 0) continue;
2031b9bf55e5SMatthew G. Knepley for (d = 0; d < coordDim; ++d) cellCoords[n * coordDim + d] = 0.0;
2032b9bf55e5SMatthew G. Knepley for (int bn = 0; bn < elem->numNodes + s; ++bn) {
2033b9bf55e5SMatthew G. Knepley if (lexorder[bn] < 0) continue;
2034b9bf55e5SMatthew G. Knepley const PetscReal *weights = sdWeights[coordDim][n];
2035b9bf55e5SMatthew G. Knepley const PetscInt bnode = elem->nodes[lexorder[bn]];
2036b9bf55e5SMatthew G. Knepley for (d = 0; d < coordDim; ++d) cellCoords[n * coordDim + d] += weights[bn] * (PetscReal)coords[bnode * 3 + d];
2037b9bf55e5SMatthew G. Knepley }
2038b9bf55e5SMatthew G. Knepley }
2039066ea43fSLisandro Dalcin }
20409566063dSJacob Faibussowitsch PetscCall(DMPlexVecSetClosure(cdm, section, coordinates, cell, cellCoords, INSERT_VALUES));
2041066ea43fSLisandro Dalcin }
20429566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion));
20439566063dSJacob Faibussowitsch PetscCall(PetscFree(cellCoords));
2044066ea43fSLisandro Dalcin } else {
2045066ea43fSLisandro Dalcin PetscInt *nodeMap;
2046066ea43fSLisandro Dalcin double *coords = mesh ? mesh->nodelist->xyz : NULL;
2047066ea43fSLisandro Dalcin PetscScalar *pointCoords;
2048066ea43fSLisandro Dalcin
20496858538eSMatthew G. Knepley PetscCall(DMGetCoordinateSection(*dm, &cs));
20506858538eSMatthew G. Knepley PetscCall(PetscSectionSetNumFields(cs, 1));
20516858538eSMatthew G. Knepley PetscCall(PetscSectionSetFieldComponents(cs, 0, coordDim));
20526858538eSMatthew G. Knepley PetscCall(PetscSectionSetChart(cs, numCells, numCells + numVerts));
20536858538eSMatthew G. Knepley for (v = numCells; v < numCells + numVerts; ++v) {
20546858538eSMatthew G. Knepley PetscCall(PetscSectionSetDof(cs, v, coordDim));
20556858538eSMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(cs, v, 0, coordDim));
2056f45c9589SStefano Zampini }
20576858538eSMatthew G. Knepley PetscCall(PetscSectionSetUp(cs));
20586858538eSMatthew G. Knepley
20596858538eSMatthew G. Knepley /* We need to localize coordinates on cells */
20600598e1a2SLisandro Dalcin if (periodic) {
20611690c2aeSBarry Smith PetscInt newStart = PETSC_INT_MAX, newEnd = -1, pStart, pEnd;
20629db5b827SMatthew G. Knepley
20636858538eSMatthew G. Knepley PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)cdmCell), &csCell));
20646858538eSMatthew G. Knepley PetscCall(PetscSectionSetNumFields(csCell, 1));
20656858538eSMatthew G. Knepley PetscCall(PetscSectionSetFieldComponents(csCell, 0, coordDim));
20669db5b827SMatthew G. Knepley for (PetscInt h = 0; h <= maxHeight; h++) {
20679db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(cdmCell, h, &pStart, &pEnd));
20689db5b827SMatthew G. Knepley newStart = PetscMin(newStart, pStart);
20699db5b827SMatthew G. Knepley newEnd = PetscMax(newEnd, pEnd);
20709db5b827SMatthew G. Knepley }
20719db5b827SMatthew G. Knepley PetscCall(PetscSectionSetChart(csCell, newStart, newEnd));
20729db5b827SMatthew G. Knepley for (PetscInt h = 0; h <= maxHeight; h++) {
20739db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(cdmCell, h, &pStart, &pEnd));
20749db5b827SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) {
20759db5b827SMatthew G. Knepley PetscInt *closure = NULL;
20769db5b827SMatthew G. Knepley PetscInt Ncl, Nv = 0;
20776858538eSMatthew G. Knepley
20789db5b827SMatthew G. Knepley if (PetscUnlikely(PetscBTLookup(periodicCells[h], p - pStart))) {
20799db5b827SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure));
20809db5b827SMatthew G. Knepley for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) {
20819db5b827SMatthew G. Knepley if (closure[cl] >= vStart && closure[cl] < vEnd) ++Nv;
20829db5b827SMatthew G. Knepley }
20839db5b827SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure));
20849db5b827SMatthew G. Knepley PetscCall(PetscSectionSetDof(csCell, p, Nv * coordDim));
20859db5b827SMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(csCell, p, 0, Nv * coordDim));
20869db5b827SMatthew G. Knepley }
2087f45c9589SStefano Zampini }
2088f45c9589SStefano Zampini }
20896858538eSMatthew G. Knepley PetscCall(PetscSectionSetUp(csCell));
20906858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateSection(*dm, PETSC_DETERMINE, csCell));
2091f45c9589SStefano Zampini }
2092066ea43fSLisandro Dalcin
20939566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(cdm, &coordinates));
20949566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &pointCoords));
20956858538eSMatthew G. Knepley PetscCall(PetscMalloc1(numVerts, &nodeMap));
20966858538eSMatthew G. Knepley for (n = 0; n < numNodes; n++)
20976858538eSMatthew G. Knepley if (mesh->vertexMap[n] >= 0) nodeMap[mesh->vertexMap[n]] = n;
20986858538eSMatthew G. Knepley for (v = 0; v < numVerts; ++v) {
20996858538eSMatthew G. Knepley PetscInt off, node = nodeMap[v];
21006858538eSMatthew G. Knepley
21016858538eSMatthew G. Knepley PetscCall(PetscSectionGetOffset(cs, numCells + v, &off));
21026858538eSMatthew G. Knepley for (d = 0; d < coordDim; ++d) pointCoords[off + d] = (PetscReal)coords[node * 3 + d];
21036858538eSMatthew G. Knepley }
21046858538eSMatthew G. Knepley PetscCall(VecRestoreArray(coordinates, &pointCoords));
21056858538eSMatthew G. Knepley
21060598e1a2SLisandro Dalcin if (periodic) {
21079db5b827SMatthew G. Knepley PetscInt cStart, cEnd;
21089db5b827SMatthew G. Knepley
21099db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(cdmCell, 0, &cStart, &cEnd));
21106858538eSMatthew G. Knepley PetscCall(DMCreateLocalVector(cdmCell, &coordinatesCell));
21116858538eSMatthew G. Knepley PetscCall(VecGetArray(coordinatesCell, &pointCoords));
21129db5b827SMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) {
21139db5b827SMatthew G. Knepley GmshElement *elem = mesh->elements + c - cStart;
21149db5b827SMatthew G. Knepley PetscInt *closure = NULL;
21159db5b827SMatthew G. Knepley PetscInt verts[8];
21169db5b827SMatthew G. Knepley PetscInt Ncl, Nv = 0;
21179db5b827SMatthew G. Knepley
21189db5b827SMatthew G. Knepley for (PetscInt v = 0; v < elem->numVerts; ++v) cone[v] = elem->nodes[v];
21199db5b827SMatthew G. Knepley PetscCall(DMPlexReorderCell(cdmCell, c, cone));
21209db5b827SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(cdmCell, c, PETSC_TRUE, &Ncl, &closure));
21219db5b827SMatthew G. Knepley for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) {
21229db5b827SMatthew G. Knepley if (closure[cl] >= vStart && closure[cl] < vEnd) verts[Nv++] = closure[cl];
2123331830f3SMatthew G. Knepley }
21249db5b827SMatthew 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);
21259db5b827SMatthew G. Knepley for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) {
21269db5b827SMatthew G. Knepley const PetscInt point = closure[cl];
21279db5b827SMatthew G. Knepley PetscInt hStart, h;
21289db5b827SMatthew G. Knepley
21299db5b827SMatthew G. Knepley PetscCall(DMPlexGetPointHeight(cdmCell, point, &h));
21309db5b827SMatthew G. Knepley if (h > maxHeight) continue;
21319db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(cdmCell, h, &hStart, NULL));
21329db5b827SMatthew G. Knepley if (PetscUnlikely(PetscBTLookup(periodicCells[h], point - hStart))) {
21339db5b827SMatthew G. Knepley PetscInt *pclosure = NULL;
21349db5b827SMatthew G. Knepley PetscInt Npcl, off, v;
21359db5b827SMatthew G. Knepley
21369db5b827SMatthew G. Knepley PetscCall(PetscSectionGetOffset(csCell, point, &off));
21379db5b827SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(cdmCell, point, PETSC_TRUE, &Npcl, &pclosure));
21389db5b827SMatthew G. Knepley for (PetscInt pcl = 0; pcl < Npcl * 2; pcl += 2) {
21399db5b827SMatthew G. Knepley if (pclosure[pcl] >= vStart && pclosure[pcl] < vEnd) {
21409db5b827SMatthew G. Knepley for (v = 0; v < Nv; ++v)
21419db5b827SMatthew G. Knepley if (verts[v] == pclosure[pcl]) break;
21429db5b827SMatthew 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);
21439db5b827SMatthew G. Knepley for (PetscInt d = 0; d < coordDim; ++d) pointCoords[off++] = (PetscReal)coords[cone[v] * 3 + d];
21449db5b827SMatthew G. Knepley ++v;
21459db5b827SMatthew G. Knepley }
21469db5b827SMatthew G. Knepley }
21479db5b827SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(cdmCell, point, PETSC_TRUE, &Npcl, &pclosure));
21489db5b827SMatthew G. Knepley }
21499db5b827SMatthew G. Knepley }
21509db5b827SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(cdmCell, c, PETSC_TRUE, &Ncl, &closure));
2151331830f3SMatthew G. Knepley }
21526858538eSMatthew G. Knepley PetscCall(VecSetBlockSize(coordinatesCell, coordDim));
21536858538eSMatthew G. Knepley PetscCall(VecRestoreArray(coordinatesCell, &pointCoords));
21546858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(*dm, coordinatesCell));
21556858538eSMatthew G. Knepley PetscCall(VecDestroy(&coordinatesCell));
2156331830f3SMatthew G. Knepley }
21579db5b827SMatthew G. Knepley PetscCall(PetscFree(nodeMap));
21586858538eSMatthew G. Knepley PetscCall(PetscSectionDestroy(&csCell));
21596858538eSMatthew G. Knepley PetscCall(DMDestroy(&cdmCell));
2160066ea43fSLisandro Dalcin }
2161066ea43fSLisandro Dalcin
21629566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
21639566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, coordDim));
21649566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(*dm, coordinates));
21659566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates));
216611c56cb0SLisandro Dalcin
21679566063dSJacob Faibussowitsch PetscCall(GmshMeshDestroy(&mesh));
21689566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&periodicVerts));
2169eae3dc7dSJacob Faibussowitsch if (periodic) {
2170eae3dc7dSJacob Faibussowitsch for (PetscInt h = 0; h <= maxHeight; ++h) PetscCall(PetscBTDestroy(periodicCells + h));
2171eae3dc7dSJacob Faibussowitsch PetscCall(PetscFree(periodicCells));
2172eae3dc7dSJacob Faibussowitsch }
217311c56cb0SLisandro Dalcin
2174066ea43fSLisandro Dalcin if (highOrder && project) {
2175066ea43fSLisandro Dalcin PetscFE fe;
2176066ea43fSLisandro Dalcin const char prefix[] = "dm_plex_gmsh_project_";
2177066ea43fSLisandro Dalcin PetscBool continuity = periodic ? PETSC_FALSE : PETSC_TRUE;
2178066ea43fSLisandro Dalcin PetscDTNodeType nodeType = PETSCDTNODES_GAUSSJACOBI;
2179066ea43fSLisandro Dalcin
2180066ea43fSLisandro Dalcin if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */
21819566063dSJacob Faibussowitsch PetscCall(GmshCreateFE(comm, prefix, isSimplex, continuity, nodeType, dim, coordDim, order, &fe));
21829566063dSJacob Faibussowitsch PetscCall(PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_project_fe_view"));
21834c712d99Sksagiyam PetscCall(DMSetCoordinateDisc(*dm, fe, PETSC_FALSE, PETSC_TRUE));
21849566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe));
2185066ea43fSLisandro Dalcin }
2186066ea43fSLisandro Dalcin
21879566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CreateGmsh, *dm, NULL, NULL, NULL));
21883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2189331830f3SMatthew G. Knepley }
2190