xref: /petsc/src/dm/impls/plex/plexgmsh.c (revision e43c9757c2fc2de09f5a402e18aa7e302d950ab0)
1331830f3SMatthew G. Knepley #define PETSCDM_DLL
2af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I   "petscdmplex.h"   I*/
3730356f6SLisandro Dalcin #include <petsc/private/hashmapi.h>
4331830f3SMatthew G. Knepley 
5066ea43fSLisandro Dalcin #include <../src/dm/impls/plex/gmshlex.h>
6066ea43fSLisandro Dalcin 
7066ea43fSLisandro Dalcin #define GMSH_LEXORDER_ITEM(T, p) \
8d71ae5a4SJacob Faibussowitsch   static int *GmshLexOrder_##T##_##p(void) \
9d71ae5a4SJacob Faibussowitsch   { \
10066ea43fSLisandro Dalcin     static int Gmsh_LexOrder_##T##_##p[GmshNumNodes_##T(p)] = {-1}; \
11066ea43fSLisandro Dalcin     int       *lex                                          = Gmsh_LexOrder_##T##_##p; \
12066ea43fSLisandro Dalcin     if (lex[0] == -1) (void)GmshLexOrder_##T(p, lex, 0); \
13066ea43fSLisandro Dalcin     return lex; \
14066ea43fSLisandro Dalcin   }
15066ea43fSLisandro Dalcin 
16d71ae5a4SJacob Faibussowitsch static int *GmshLexOrder_QUA_2_Serendipity(void)
17d71ae5a4SJacob Faibussowitsch {
18b9bf55e5SMatthew G. Knepley   static int Gmsh_LexOrder_QUA_2_Serendipity[9] = {-1};
19b9bf55e5SMatthew G. Knepley   int       *lex                                = Gmsh_LexOrder_QUA_2_Serendipity;
20b9bf55e5SMatthew G. Knepley   if (lex[0] == -1) {
21b9bf55e5SMatthew G. Knepley     /* Vertices */
229371c9d4SSatish Balay     lex[0] = 0;
239371c9d4SSatish Balay     lex[2] = 1;
249371c9d4SSatish Balay     lex[8] = 2;
259371c9d4SSatish Balay     lex[6] = 3;
26b9bf55e5SMatthew G. Knepley     /* Edges */
279371c9d4SSatish Balay     lex[1] = 4;
289371c9d4SSatish Balay     lex[5] = 5;
299371c9d4SSatish Balay     lex[7] = 6;
309371c9d4SSatish Balay     lex[3] = 7;
31b9bf55e5SMatthew G. Knepley     /* Cell */
32b9bf55e5SMatthew G. Knepley     lex[4] = -8;
33b9bf55e5SMatthew G. Knepley   }
34b9bf55e5SMatthew G. Knepley   return lex;
35b9bf55e5SMatthew G. Knepley }
36b9bf55e5SMatthew G. Knepley 
37d71ae5a4SJacob Faibussowitsch static int *GmshLexOrder_HEX_2_Serendipity(void)
38d71ae5a4SJacob Faibussowitsch {
39b9bf55e5SMatthew G. Knepley   static int Gmsh_LexOrder_HEX_2_Serendipity[27] = {-1};
40b9bf55e5SMatthew G. Knepley   int       *lex                                 = Gmsh_LexOrder_HEX_2_Serendipity;
41b9bf55e5SMatthew G. Knepley   if (lex[0] == -1) {
42b9bf55e5SMatthew G. Knepley     /* Vertices */
439371c9d4SSatish Balay     lex[0]  = 0;
449371c9d4SSatish Balay     lex[2]  = 1;
459371c9d4SSatish Balay     lex[8]  = 2;
469371c9d4SSatish Balay     lex[6]  = 3;
479371c9d4SSatish Balay     lex[18] = 4;
489371c9d4SSatish Balay     lex[20] = 5;
499371c9d4SSatish Balay     lex[26] = 6;
509371c9d4SSatish Balay     lex[24] = 7;
51b9bf55e5SMatthew G. Knepley     /* Edges */
529371c9d4SSatish Balay     lex[1]  = 8;
539371c9d4SSatish Balay     lex[3]  = 9;
549371c9d4SSatish Balay     lex[9]  = 10;
559371c9d4SSatish Balay     lex[5]  = 11;
569371c9d4SSatish Balay     lex[11] = 12;
579371c9d4SSatish Balay     lex[7]  = 13;
589371c9d4SSatish Balay     lex[17] = 14;
599371c9d4SSatish Balay     lex[15] = 15;
609371c9d4SSatish Balay     lex[19] = 16;
619371c9d4SSatish Balay     lex[21] = 17;
629371c9d4SSatish Balay     lex[23] = 18;
639371c9d4SSatish Balay     lex[25] = 19;
64b9bf55e5SMatthew G. Knepley     /* Faces */
659371c9d4SSatish Balay     lex[4]  = -20;
669371c9d4SSatish Balay     lex[10] = -21;
679371c9d4SSatish Balay     lex[12] = -22;
689371c9d4SSatish Balay     lex[14] = -23;
699371c9d4SSatish Balay     lex[16] = -24;
709371c9d4SSatish Balay     lex[22] = -25;
71b9bf55e5SMatthew G. Knepley     /* Cell */
72b9bf55e5SMatthew G. Knepley     lex[13] = -26;
73b9bf55e5SMatthew G. Knepley   }
74b9bf55e5SMatthew G. Knepley   return lex;
75b9bf55e5SMatthew G. Knepley }
76b9bf55e5SMatthew G. Knepley 
77066ea43fSLisandro Dalcin #define GMSH_LEXORDER_LIST(T) \
78066ea43fSLisandro Dalcin   GMSH_LEXORDER_ITEM(T, 1) \
79066ea43fSLisandro Dalcin   GMSH_LEXORDER_ITEM(T, 2) \
80066ea43fSLisandro Dalcin   GMSH_LEXORDER_ITEM(T, 3) \
81066ea43fSLisandro Dalcin   GMSH_LEXORDER_ITEM(T, 4) \
82066ea43fSLisandro Dalcin   GMSH_LEXORDER_ITEM(T, 5) \
83066ea43fSLisandro Dalcin   GMSH_LEXORDER_ITEM(T, 6) \
84066ea43fSLisandro Dalcin   GMSH_LEXORDER_ITEM(T, 7) \
85066ea43fSLisandro Dalcin   GMSH_LEXORDER_ITEM(T, 8) \
86066ea43fSLisandro Dalcin   GMSH_LEXORDER_ITEM(T, 9) \
87066ea43fSLisandro Dalcin   GMSH_LEXORDER_ITEM(T, 10)
88066ea43fSLisandro Dalcin 
89066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(VTX, 0)
90066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(SEG)
91066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(TRI)
92066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(QUA)
93066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(TET)
94066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(HEX)
95066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(PRI)
96066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(PYR)
97066ea43fSLisandro Dalcin 
98066ea43fSLisandro Dalcin typedef enum {
99066ea43fSLisandro Dalcin   GMSH_VTX           = 0,
100066ea43fSLisandro Dalcin   GMSH_SEG           = 1,
101066ea43fSLisandro Dalcin   GMSH_TRI           = 2,
102066ea43fSLisandro Dalcin   GMSH_QUA           = 3,
103066ea43fSLisandro Dalcin   GMSH_TET           = 4,
104066ea43fSLisandro Dalcin   GMSH_HEX           = 5,
105066ea43fSLisandro Dalcin   GMSH_PRI           = 6,
106066ea43fSLisandro Dalcin   GMSH_PYR           = 7,
107066ea43fSLisandro Dalcin   GMSH_NUM_POLYTOPES = 8
108066ea43fSLisandro Dalcin } GmshPolytopeType;
109066ea43fSLisandro Dalcin 
110de78e4feSLisandro Dalcin typedef struct {
1110598e1a2SLisandro Dalcin   int cellType;
112066ea43fSLisandro Dalcin   int polytope;
1130598e1a2SLisandro Dalcin   int dim;
1140598e1a2SLisandro Dalcin   int order;
115066ea43fSLisandro Dalcin   int numVerts;
1160598e1a2SLisandro Dalcin   int numNodes;
117066ea43fSLisandro Dalcin   int *(*lexorder)(void);
1180598e1a2SLisandro Dalcin } GmshCellInfo;
1190598e1a2SLisandro Dalcin 
12010dd146fSPierre Jolivet // clang-format off
12110dd146fSPierre Jolivet #define GmshCellEntry(cellType, polytope, dim, order) {cellType, GMSH_##polytope, dim, order, GmshNumNodes_##polytope(1), GmshNumNodes_##polytope(order), GmshLexOrder_##polytope##_##order}
12210dd146fSPierre Jolivet // clang-format on
1230598e1a2SLisandro Dalcin 
1240598e1a2SLisandro Dalcin static const GmshCellInfo GmshCellTable[] = {
125066ea43fSLisandro Dalcin   GmshCellEntry(15, VTX, 0, 0),
1260598e1a2SLisandro Dalcin 
1279371c9d4SSatish Balay   GmshCellEntry(1, SEG, 1, 1),   GmshCellEntry(8, SEG, 1, 2),   GmshCellEntry(26, SEG, 1, 3),
1289371c9d4SSatish Balay   GmshCellEntry(27, SEG, 1, 4),  GmshCellEntry(28, SEG, 1, 5),  GmshCellEntry(62, SEG, 1, 6),
1299371c9d4SSatish Balay   GmshCellEntry(63, SEG, 1, 7),  GmshCellEntry(64, SEG, 1, 8),  GmshCellEntry(65, SEG, 1, 9),
130066ea43fSLisandro Dalcin   GmshCellEntry(66, SEG, 1, 10),
1310598e1a2SLisandro Dalcin 
1329371c9d4SSatish Balay   GmshCellEntry(2, TRI, 2, 1),   GmshCellEntry(9, TRI, 2, 2),   GmshCellEntry(21, TRI, 2, 3),
1339371c9d4SSatish Balay   GmshCellEntry(23, TRI, 2, 4),  GmshCellEntry(25, TRI, 2, 5),  GmshCellEntry(42, TRI, 2, 6),
1349371c9d4SSatish Balay   GmshCellEntry(43, TRI, 2, 7),  GmshCellEntry(44, TRI, 2, 8),  GmshCellEntry(45, TRI, 2, 9),
135066ea43fSLisandro Dalcin   GmshCellEntry(46, TRI, 2, 10),
1360598e1a2SLisandro Dalcin 
1379371c9d4SSatish Balay   GmshCellEntry(3, QUA, 2, 1),   GmshCellEntry(10, QUA, 2, 2),  {16, GMSH_QUA, 2, 2, 4, 8,  GmshLexOrder_QUA_2_Serendipity},
1389371c9d4SSatish Balay   GmshCellEntry(36, QUA, 2, 3),  GmshCellEntry(37, QUA, 2, 4),  GmshCellEntry(38, QUA, 2, 5),
1399371c9d4SSatish Balay   GmshCellEntry(47, QUA, 2, 6),  GmshCellEntry(48, QUA, 2, 7),  GmshCellEntry(49, QUA, 2, 8),
1409371c9d4SSatish Balay   GmshCellEntry(50, QUA, 2, 9),  GmshCellEntry(51, QUA, 2, 10),
1410598e1a2SLisandro Dalcin 
1429371c9d4SSatish Balay   GmshCellEntry(4, TET, 3, 1),   GmshCellEntry(11, TET, 3, 2),  GmshCellEntry(29, TET, 3, 3),
1439371c9d4SSatish Balay   GmshCellEntry(30, TET, 3, 4),  GmshCellEntry(31, TET, 3, 5),  GmshCellEntry(71, TET, 3, 6),
1449371c9d4SSatish Balay   GmshCellEntry(72, TET, 3, 7),  GmshCellEntry(73, TET, 3, 8),  GmshCellEntry(74, TET, 3, 9),
145066ea43fSLisandro Dalcin   GmshCellEntry(75, TET, 3, 10),
1460598e1a2SLisandro Dalcin 
1479371c9d4SSatish Balay   GmshCellEntry(5, HEX, 3, 1),   GmshCellEntry(12, HEX, 3, 2),  {17, GMSH_HEX, 3, 2, 8, 20, GmshLexOrder_HEX_2_Serendipity},
1489371c9d4SSatish Balay   GmshCellEntry(92, HEX, 3, 3),  GmshCellEntry(93, HEX, 3, 4),  GmshCellEntry(94, HEX, 3, 5),
1499371c9d4SSatish Balay   GmshCellEntry(95, HEX, 3, 6),  GmshCellEntry(96, HEX, 3, 7),  GmshCellEntry(97, HEX, 3, 8),
1509371c9d4SSatish Balay   GmshCellEntry(98, HEX, 3, 9),  GmshCellEntry(-1, HEX, 3, 10),
1510598e1a2SLisandro Dalcin 
1529371c9d4SSatish Balay   GmshCellEntry(6, PRI, 3, 1),   GmshCellEntry(13, PRI, 3, 2),  GmshCellEntry(90, PRI, 3, 3),
1539371c9d4SSatish Balay   GmshCellEntry(91, PRI, 3, 4),  GmshCellEntry(106, PRI, 3, 5), GmshCellEntry(107, PRI, 3, 6),
1549371c9d4SSatish Balay   GmshCellEntry(108, PRI, 3, 7), GmshCellEntry(109, PRI, 3, 8), GmshCellEntry(110, PRI, 3, 9),
155066ea43fSLisandro Dalcin   GmshCellEntry(-1, PRI, 3, 10),
1560598e1a2SLisandro Dalcin 
1579371c9d4SSatish Balay   GmshCellEntry(7, PYR, 3, 1),   GmshCellEntry(14, PYR, 3, 2),  GmshCellEntry(118, PYR, 3, 3),
1589371c9d4SSatish Balay   GmshCellEntry(119, PYR, 3, 4), GmshCellEntry(120, PYR, 3, 5), GmshCellEntry(121, PYR, 3, 6),
1599371c9d4SSatish Balay   GmshCellEntry(122, PYR, 3, 7), GmshCellEntry(123, PYR, 3, 8), GmshCellEntry(124, PYR, 3, 9),
160066ea43fSLisandro Dalcin   GmshCellEntry(-1, PYR, 3, 10)
1610598e1a2SLisandro Dalcin 
1620598e1a2SLisandro Dalcin #if 0
163066ea43fSLisandro Dalcin   {20, GMSH_TRI, 2, 3, 3,  9, NULL},
164066ea43fSLisandro Dalcin   {18, GMSH_PRI, 3, 2, 6, 15, NULL},
165066ea43fSLisandro Dalcin   {19, GMSH_PYR, 3, 2, 5, 13, NULL},
1660598e1a2SLisandro Dalcin #endif
1670598e1a2SLisandro Dalcin };
1680598e1a2SLisandro Dalcin 
1690598e1a2SLisandro Dalcin static GmshCellInfo GmshCellMap[150];
1700598e1a2SLisandro Dalcin 
171d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshCellInfoSetUp(void)
172d71ae5a4SJacob Faibussowitsch {
1730598e1a2SLisandro Dalcin   size_t           i, n;
1740598e1a2SLisandro Dalcin   static PetscBool called = PETSC_FALSE;
1750598e1a2SLisandro Dalcin 
1760598e1a2SLisandro Dalcin   PetscFunctionBegin;
1774d86920dSPierre Jolivet   if (called) PetscFunctionReturn(PETSC_SUCCESS);
1780598e1a2SLisandro Dalcin   called = PETSC_TRUE;
179dd39110bSPierre Jolivet   n      = PETSC_STATIC_ARRAY_LENGTH(GmshCellMap);
1800598e1a2SLisandro Dalcin   for (i = 0; i < n; ++i) {
1810598e1a2SLisandro Dalcin     GmshCellMap[i].cellType = -1;
182066ea43fSLisandro Dalcin     GmshCellMap[i].polytope = -1;
1830598e1a2SLisandro Dalcin   }
184dd39110bSPierre Jolivet   n = PETSC_STATIC_ARRAY_LENGTH(GmshCellTable);
185066ea43fSLisandro Dalcin   for (i = 0; i < n; ++i) {
186066ea43fSLisandro Dalcin     if (GmshCellTable[i].cellType <= 0) continue;
187066ea43fSLisandro Dalcin     GmshCellMap[GmshCellTable[i].cellType] = GmshCellTable[i];
188066ea43fSLisandro Dalcin   }
1893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1900598e1a2SLisandro Dalcin }
1910598e1a2SLisandro Dalcin 
1929371c9d4SSatish Balay #define GmshCellTypeCheck(ct) \
1939371c9d4SSatish Balay   PetscMacroReturnStandard(const int _ct_ = (int)ct; PetscCheck(_ct_ >= 0 && _ct_ < (int)PETSC_STATIC_ARRAY_LENGTH(GmshCellMap), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid Gmsh element type %d", _ct_); PetscCheck(GmshCellMap[_ct_].cellType == _ct_, PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported Gmsh element type %d", _ct_); \
1949371c9d4SSatish Balay                            PetscCheck(GmshCellMap[_ct_].polytope != -1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported Gmsh element type %d", _ct_);)
1950598e1a2SLisandro Dalcin 
1960598e1a2SLisandro Dalcin typedef struct {
197698a79b9SLisandro Dalcin   PetscViewer viewer;
198698a79b9SLisandro Dalcin   int         fileFormat;
199698a79b9SLisandro Dalcin   int         dataSize;
200698a79b9SLisandro Dalcin   PetscBool   binary;
201698a79b9SLisandro Dalcin   PetscBool   byteSwap;
202698a79b9SLisandro Dalcin   size_t      wlen;
203698a79b9SLisandro Dalcin   void       *wbuf;
204698a79b9SLisandro Dalcin   size_t      slen;
205698a79b9SLisandro Dalcin   void       *sbuf;
2060598e1a2SLisandro Dalcin   PetscInt   *nbuf;
2070598e1a2SLisandro Dalcin   PetscInt    nodeStart;
2080598e1a2SLisandro Dalcin   PetscInt    nodeEnd;
20933a088b6SMatthew G. Knepley   PetscInt   *nodeMap;
210698a79b9SLisandro Dalcin } GmshFile;
211de78e4feSLisandro Dalcin 
212d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshBufferGet(GmshFile *gmsh, size_t count, size_t eltsize, void *buf)
213d71ae5a4SJacob Faibussowitsch {
214de78e4feSLisandro Dalcin   size_t size = count * eltsize;
21511c56cb0SLisandro Dalcin 
21611c56cb0SLisandro Dalcin   PetscFunctionBegin;
217698a79b9SLisandro Dalcin   if (gmsh->wlen < size) {
2189566063dSJacob Faibussowitsch     PetscCall(PetscFree(gmsh->wbuf));
2199566063dSJacob Faibussowitsch     PetscCall(PetscMalloc(size, &gmsh->wbuf));
220698a79b9SLisandro Dalcin     gmsh->wlen = size;
221de78e4feSLisandro Dalcin   }
222698a79b9SLisandro Dalcin   *(void **)buf = size ? gmsh->wbuf : NULL;
2233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
224de78e4feSLisandro Dalcin }
225de78e4feSLisandro Dalcin 
226d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshBufferSizeGet(GmshFile *gmsh, size_t count, void *buf)
227d71ae5a4SJacob Faibussowitsch {
228698a79b9SLisandro Dalcin   size_t dataSize = (size_t)gmsh->dataSize;
229698a79b9SLisandro Dalcin   size_t size     = count * dataSize;
230698a79b9SLisandro Dalcin 
231698a79b9SLisandro Dalcin   PetscFunctionBegin;
232698a79b9SLisandro Dalcin   if (gmsh->slen < size) {
2339566063dSJacob Faibussowitsch     PetscCall(PetscFree(gmsh->sbuf));
2349566063dSJacob Faibussowitsch     PetscCall(PetscMalloc(size, &gmsh->sbuf));
235698a79b9SLisandro Dalcin     gmsh->slen = size;
236698a79b9SLisandro Dalcin   }
237698a79b9SLisandro Dalcin   *(void **)buf = size ? gmsh->sbuf : NULL;
2383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
239698a79b9SLisandro Dalcin }
240698a79b9SLisandro Dalcin 
241d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshRead(GmshFile *gmsh, void *buf, PetscInt count, PetscDataType dtype)
242d71ae5a4SJacob Faibussowitsch {
243de78e4feSLisandro Dalcin   PetscFunctionBegin;
2449566063dSJacob Faibussowitsch   PetscCall(PetscViewerRead(gmsh->viewer, buf, count, NULL, dtype));
2459566063dSJacob Faibussowitsch   if (gmsh->byteSwap) PetscCall(PetscByteSwap(buf, dtype, count));
2463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
247698a79b9SLisandro Dalcin }
248698a79b9SLisandro Dalcin 
249d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadString(GmshFile *gmsh, char *buf, PetscInt count)
250d71ae5a4SJacob Faibussowitsch {
251698a79b9SLisandro Dalcin   PetscFunctionBegin;
2529566063dSJacob Faibussowitsch   PetscCall(PetscViewerRead(gmsh->viewer, buf, count, NULL, PETSC_STRING));
2533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
254698a79b9SLisandro Dalcin }
255698a79b9SLisandro Dalcin 
256d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshMatch(PETSC_UNUSED GmshFile *gmsh, const char Section[], char line[PETSC_MAX_PATH_LEN], PetscBool *match)
257d71ae5a4SJacob Faibussowitsch {
258d6689ca9SLisandro Dalcin   PetscFunctionBegin;
2599566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(line, Section, match));
2603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
261d6689ca9SLisandro Dalcin }
262d6689ca9SLisandro Dalcin 
263d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshExpect(GmshFile *gmsh, const char Section[], char line[PETSC_MAX_PATH_LEN])
264d71ae5a4SJacob Faibussowitsch {
265d6689ca9SLisandro Dalcin   PetscBool match;
266d6689ca9SLisandro Dalcin 
267d6689ca9SLisandro Dalcin   PetscFunctionBegin;
2689566063dSJacob Faibussowitsch   PetscCall(GmshMatch(gmsh, Section, line, &match));
26900045ab3SPierre Jolivet   PetscCheck(match, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file, expecting %s, not %s", Section, line);
2703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
271d6689ca9SLisandro Dalcin }
272d6689ca9SLisandro Dalcin 
273d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadSection(GmshFile *gmsh, char line[PETSC_MAX_PATH_LEN])
274d71ae5a4SJacob Faibussowitsch {
275d6689ca9SLisandro Dalcin   PetscBool match;
276d6689ca9SLisandro Dalcin 
277d6689ca9SLisandro Dalcin   PetscFunctionBegin;
278d6689ca9SLisandro Dalcin   while (PETSC_TRUE) {
2799566063dSJacob Faibussowitsch     PetscCall(GmshReadString(gmsh, line, 1));
2809566063dSJacob Faibussowitsch     PetscCall(GmshMatch(gmsh, "$Comments", line, &match));
281d6689ca9SLisandro Dalcin     if (!match) break;
282d6689ca9SLisandro Dalcin     while (PETSC_TRUE) {
2839566063dSJacob Faibussowitsch       PetscCall(GmshReadString(gmsh, line, 1));
2849566063dSJacob Faibussowitsch       PetscCall(GmshMatch(gmsh, "$EndComments", line, &match));
285d6689ca9SLisandro Dalcin       if (match) break;
286d6689ca9SLisandro Dalcin     }
287d6689ca9SLisandro Dalcin   }
2883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
289d6689ca9SLisandro Dalcin }
290d6689ca9SLisandro Dalcin 
291d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEndSection(GmshFile *gmsh, const char EndSection[], char line[PETSC_MAX_PATH_LEN])
292d71ae5a4SJacob Faibussowitsch {
293d6689ca9SLisandro Dalcin   PetscFunctionBegin;
2949566063dSJacob Faibussowitsch   PetscCall(GmshReadString(gmsh, line, 1));
2959566063dSJacob Faibussowitsch   PetscCall(GmshExpect(gmsh, EndSection, line));
2963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
297d6689ca9SLisandro Dalcin }
298d6689ca9SLisandro Dalcin 
299d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadSize(GmshFile *gmsh, PetscInt *buf, PetscInt count)
300d71ae5a4SJacob Faibussowitsch {
301698a79b9SLisandro Dalcin   PetscInt i;
302698a79b9SLisandro Dalcin   size_t   dataSize = (size_t)gmsh->dataSize;
303698a79b9SLisandro Dalcin 
304698a79b9SLisandro Dalcin   PetscFunctionBegin;
305698a79b9SLisandro Dalcin   if (dataSize == sizeof(PetscInt)) {
3069566063dSJacob Faibussowitsch     PetscCall(GmshRead(gmsh, buf, count, PETSC_INT));
307698a79b9SLisandro Dalcin   } else if (dataSize == sizeof(int)) {
308698a79b9SLisandro Dalcin     int *ibuf = NULL;
3099566063dSJacob Faibussowitsch     PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf));
3109566063dSJacob Faibussowitsch     PetscCall(GmshRead(gmsh, ibuf, count, PETSC_ENUM));
311698a79b9SLisandro Dalcin     for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i];
312698a79b9SLisandro Dalcin   } else if (dataSize == sizeof(long)) {
313698a79b9SLisandro Dalcin     long *ibuf = NULL;
3149566063dSJacob Faibussowitsch     PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf));
3159566063dSJacob Faibussowitsch     PetscCall(GmshRead(gmsh, ibuf, count, PETSC_LONG));
316698a79b9SLisandro Dalcin     for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i];
317698a79b9SLisandro Dalcin   } else if (dataSize == sizeof(PetscInt64)) {
318698a79b9SLisandro Dalcin     PetscInt64 *ibuf = NULL;
3199566063dSJacob Faibussowitsch     PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf));
3209566063dSJacob Faibussowitsch     PetscCall(GmshRead(gmsh, ibuf, count, PETSC_INT64));
321698a79b9SLisandro Dalcin     for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i];
322698a79b9SLisandro Dalcin   }
3233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
324698a79b9SLisandro Dalcin }
325698a79b9SLisandro Dalcin 
326d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadInt(GmshFile *gmsh, int *buf, PetscInt count)
327d71ae5a4SJacob Faibussowitsch {
328698a79b9SLisandro Dalcin   PetscFunctionBegin;
3299566063dSJacob Faibussowitsch   PetscCall(GmshRead(gmsh, buf, count, PETSC_ENUM));
3303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
331698a79b9SLisandro Dalcin }
332698a79b9SLisandro Dalcin 
333d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadDouble(GmshFile *gmsh, double *buf, PetscInt count)
334d71ae5a4SJacob Faibussowitsch {
335698a79b9SLisandro Dalcin   PetscFunctionBegin;
3369566063dSJacob Faibussowitsch   PetscCall(GmshRead(gmsh, buf, count, PETSC_DOUBLE));
3373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
338de78e4feSLisandro Dalcin }
339de78e4feSLisandro Dalcin 
3409c0edc59SMatthew G. Knepley #define GMSH_MAX_TAGS 16
3417d5b9244SMatthew G. Knepley 
342de78e4feSLisandro Dalcin typedef struct {
3430598e1a2SLisandro Dalcin   PetscInt id;                  /* Entity ID */
3440598e1a2SLisandro Dalcin   PetscInt dim;                 /* Dimension */
345de78e4feSLisandro Dalcin   double   bbox[6];             /* Bounding box */
346de78e4feSLisandro Dalcin   PetscInt numTags;             /* Size of tag array */
3477d5b9244SMatthew G. Knepley   int      tags[GMSH_MAX_TAGS]; /* Tag array */
348de78e4feSLisandro Dalcin } GmshEntity;
349de78e4feSLisandro Dalcin 
350de78e4feSLisandro Dalcin typedef struct {
351730356f6SLisandro Dalcin   GmshEntity *entity[4];
352730356f6SLisandro Dalcin   PetscHMapI  entityMap[4];
353730356f6SLisandro Dalcin } GmshEntities;
354730356f6SLisandro Dalcin 
355d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshEntitiesCreate(PetscInt count[4], GmshEntities **entities)
356d71ae5a4SJacob Faibussowitsch {
357730356f6SLisandro Dalcin   PetscInt dim;
358730356f6SLisandro Dalcin 
359730356f6SLisandro Dalcin   PetscFunctionBegin;
3609566063dSJacob Faibussowitsch   PetscCall(PetscNew(entities));
361730356f6SLisandro Dalcin   for (dim = 0; dim < 4; ++dim) {
3629566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(count[dim], &(*entities)->entity[dim]));
3639566063dSJacob Faibussowitsch     PetscCall(PetscHMapICreate(&(*entities)->entityMap[dim]));
364730356f6SLisandro Dalcin   }
3653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
366730356f6SLisandro Dalcin }
367730356f6SLisandro Dalcin 
368d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshEntitiesDestroy(GmshEntities **entities)
369d71ae5a4SJacob Faibussowitsch {
3700598e1a2SLisandro Dalcin   PetscInt dim;
3710598e1a2SLisandro Dalcin 
3720598e1a2SLisandro Dalcin   PetscFunctionBegin;
3733ba16761SJacob Faibussowitsch   if (!*entities) PetscFunctionReturn(PETSC_SUCCESS);
3740598e1a2SLisandro Dalcin   for (dim = 0; dim < 4; ++dim) {
3759566063dSJacob Faibussowitsch     PetscCall(PetscFree((*entities)->entity[dim]));
3769566063dSJacob Faibussowitsch     PetscCall(PetscHMapIDestroy(&(*entities)->entityMap[dim]));
3770598e1a2SLisandro Dalcin   }
378f4f49eeaSPierre Jolivet   PetscCall(PetscFree(*entities));
3793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3800598e1a2SLisandro Dalcin }
3810598e1a2SLisandro Dalcin 
382d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshEntitiesAdd(GmshEntities *entities, PetscInt index, PetscInt dim, PetscInt eid, GmshEntity **entity)
383d71ae5a4SJacob Faibussowitsch {
384730356f6SLisandro Dalcin   PetscFunctionBegin;
3859566063dSJacob Faibussowitsch   PetscCall(PetscHMapISet(entities->entityMap[dim], eid, index));
386730356f6SLisandro Dalcin   entities->entity[dim][index].dim = dim;
387730356f6SLisandro Dalcin   entities->entity[dim][index].id  = eid;
388730356f6SLisandro Dalcin   if (entity) *entity = &entities->entity[dim][index];
3893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
390730356f6SLisandro Dalcin }
391730356f6SLisandro Dalcin 
392d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshEntitiesGet(GmshEntities *entities, PetscInt dim, PetscInt eid, GmshEntity **entity)
393d71ae5a4SJacob Faibussowitsch {
394730356f6SLisandro Dalcin   PetscInt index;
395730356f6SLisandro Dalcin 
396730356f6SLisandro Dalcin   PetscFunctionBegin;
3979566063dSJacob Faibussowitsch   PetscCall(PetscHMapIGet(entities->entityMap[dim], eid, &index));
398730356f6SLisandro Dalcin   *entity = &entities->entity[dim][index];
3993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
400730356f6SLisandro Dalcin }
401730356f6SLisandro Dalcin 
4020598e1a2SLisandro Dalcin typedef struct {
4030598e1a2SLisandro Dalcin   PetscInt *id;  /* Node IDs */
4040598e1a2SLisandro Dalcin   double   *xyz; /* Coordinates */
40581a1af93SMatthew G. Knepley   PetscInt *tag; /* Physical tag */
4060598e1a2SLisandro Dalcin } GmshNodes;
4070598e1a2SLisandro Dalcin 
408d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshNodesCreate(PetscInt count, GmshNodes **nodes)
409d71ae5a4SJacob Faibussowitsch {
410730356f6SLisandro Dalcin   PetscFunctionBegin;
4119566063dSJacob Faibussowitsch   PetscCall(PetscNew(nodes));
4129566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(count * 1, &(*nodes)->id));
4139566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(count * 3, &(*nodes)->xyz));
4147d5b9244SMatthew G. Knepley   PetscCall(PetscMalloc1(count * GMSH_MAX_TAGS, &(*nodes)->tag));
4153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
416730356f6SLisandro Dalcin }
4170598e1a2SLisandro Dalcin 
418d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshNodesDestroy(GmshNodes **nodes)
419d71ae5a4SJacob Faibussowitsch {
4200598e1a2SLisandro Dalcin   PetscFunctionBegin;
4213ba16761SJacob Faibussowitsch   if (!*nodes) PetscFunctionReturn(PETSC_SUCCESS);
4229566063dSJacob Faibussowitsch   PetscCall(PetscFree((*nodes)->id));
4239566063dSJacob Faibussowitsch   PetscCall(PetscFree((*nodes)->xyz));
4249566063dSJacob Faibussowitsch   PetscCall(PetscFree((*nodes)->tag));
425f4f49eeaSPierre Jolivet   PetscCall(PetscFree(*nodes));
4263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
427730356f6SLisandro Dalcin }
428730356f6SLisandro Dalcin 
429730356f6SLisandro Dalcin typedef struct {
4300598e1a2SLisandro Dalcin   PetscInt  id;                  /* Element ID */
4310598e1a2SLisandro Dalcin   PetscInt  dim;                 /* Dimension */
432de78e4feSLisandro Dalcin   PetscInt  cellType;            /* Cell type */
4330598e1a2SLisandro Dalcin   PetscInt  numVerts;            /* Size of vertex array */
434de78e4feSLisandro Dalcin   PetscInt  numNodes;            /* Size of node array */
4350598e1a2SLisandro Dalcin   PetscInt *nodes;               /* Vertex/Node array */
43681a1af93SMatthew G. Knepley   PetscInt  numTags;             /* Size of physical tag array */
4377d5b9244SMatthew G. Knepley   int       tags[GMSH_MAX_TAGS]; /* Physical tag array */
438de78e4feSLisandro Dalcin } GmshElement;
439de78e4feSLisandro Dalcin 
440d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshElementsCreate(PetscInt count, GmshElement **elements)
441d71ae5a4SJacob Faibussowitsch {
4420598e1a2SLisandro Dalcin   PetscFunctionBegin;
4439566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(count, elements));
4443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4450598e1a2SLisandro Dalcin }
4460598e1a2SLisandro Dalcin 
447d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshElementsDestroy(GmshElement **elements)
448d71ae5a4SJacob Faibussowitsch {
4490598e1a2SLisandro Dalcin   PetscFunctionBegin;
4503ba16761SJacob Faibussowitsch   if (!*elements) PetscFunctionReturn(PETSC_SUCCESS);
4519566063dSJacob Faibussowitsch   PetscCall(PetscFree(*elements));
4523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4530598e1a2SLisandro Dalcin }
4540598e1a2SLisandro Dalcin 
4550598e1a2SLisandro Dalcin typedef struct {
4560598e1a2SLisandro Dalcin   PetscInt       dim;
457066ea43fSLisandro Dalcin   PetscInt       order;
4580598e1a2SLisandro Dalcin   GmshEntities  *entities;
4590598e1a2SLisandro Dalcin   PetscInt       numNodes;
4600598e1a2SLisandro Dalcin   GmshNodes     *nodelist;
4610598e1a2SLisandro Dalcin   PetscInt       numElems;
4620598e1a2SLisandro Dalcin   GmshElement   *elements;
4630598e1a2SLisandro Dalcin   PetscInt       numVerts;
4640598e1a2SLisandro Dalcin   PetscInt       numCells;
4650598e1a2SLisandro Dalcin   PetscInt      *periodMap;
4660598e1a2SLisandro Dalcin   PetscInt      *vertexMap;
4670598e1a2SLisandro Dalcin   PetscSegBuffer segbuf;
468a45dabc8SMatthew G. Knepley   PetscInt       numRegions;
46990d778b8SLisandro Dalcin   PetscInt      *regionDims;
470a45dabc8SMatthew G. Knepley   PetscInt      *regionTags;
471a45dabc8SMatthew G. Knepley   char         **regionNames;
4720598e1a2SLisandro Dalcin } GmshMesh;
4730598e1a2SLisandro Dalcin 
474d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshMeshCreate(GmshMesh **mesh)
475d71ae5a4SJacob Faibussowitsch {
4760598e1a2SLisandro Dalcin   PetscFunctionBegin;
4779566063dSJacob Faibussowitsch   PetscCall(PetscNew(mesh));
4789566063dSJacob Faibussowitsch   PetscCall(PetscSegBufferCreate(sizeof(PetscInt), 0, &(*mesh)->segbuf));
4793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4800598e1a2SLisandro Dalcin }
4810598e1a2SLisandro Dalcin 
482d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshMeshDestroy(GmshMesh **mesh)
483d71ae5a4SJacob Faibussowitsch {
484a45dabc8SMatthew G. Knepley   PetscInt r;
4850598e1a2SLisandro Dalcin 
4860598e1a2SLisandro Dalcin   PetscFunctionBegin;
4873ba16761SJacob Faibussowitsch   if (!*mesh) PetscFunctionReturn(PETSC_SUCCESS);
4889566063dSJacob Faibussowitsch   PetscCall(GmshEntitiesDestroy(&(*mesh)->entities));
4899566063dSJacob Faibussowitsch   PetscCall(GmshNodesDestroy(&(*mesh)->nodelist));
4909566063dSJacob Faibussowitsch   PetscCall(GmshElementsDestroy(&(*mesh)->elements));
4919566063dSJacob Faibussowitsch   PetscCall(PetscFree((*mesh)->periodMap));
4929566063dSJacob Faibussowitsch   PetscCall(PetscFree((*mesh)->vertexMap));
4939566063dSJacob Faibussowitsch   PetscCall(PetscSegBufferDestroy(&(*mesh)->segbuf));
4949566063dSJacob Faibussowitsch   for (r = 0; r < (*mesh)->numRegions; ++r) PetscCall(PetscFree((*mesh)->regionNames[r]));
49590d778b8SLisandro Dalcin   PetscCall(PetscFree3((*mesh)->regionDims, (*mesh)->regionTags, (*mesh)->regionNames));
496f4f49eeaSPierre Jolivet   PetscCall(PetscFree(*mesh));
4973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4980598e1a2SLisandro Dalcin }
4990598e1a2SLisandro Dalcin 
500d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes_v22(GmshFile *gmsh, GmshMesh *mesh)
501d71ae5a4SJacob Faibussowitsch {
502698a79b9SLisandro Dalcin   PetscViewer viewer   = gmsh->viewer;
503698a79b9SLisandro Dalcin   PetscBool   byteSwap = gmsh->byteSwap;
504de78e4feSLisandro Dalcin   char        line[PETSC_MAX_PATH_LEN];
5057d5b9244SMatthew G. Knepley   int         n, t, num, nid, snum;
5060598e1a2SLisandro Dalcin   GmshNodes  *nodes;
507de78e4feSLisandro Dalcin 
508de78e4feSLisandro Dalcin   PetscFunctionBegin;
5099566063dSJacob Faibussowitsch   PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING));
510698a79b9SLisandro Dalcin   snum = sscanf(line, "%d", &num);
51108401ef6SPierre Jolivet   PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
5129566063dSJacob Faibussowitsch   PetscCall(GmshNodesCreate(num, &nodes));
5130598e1a2SLisandro Dalcin   mesh->numNodes = num;
5140598e1a2SLisandro Dalcin   mesh->nodelist = nodes;
5150598e1a2SLisandro Dalcin   for (n = 0; n < num; ++n) {
5160598e1a2SLisandro Dalcin     double *xyz = nodes->xyz + n * 3;
5179566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM));
5189566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE));
5199566063dSJacob Faibussowitsch     if (byteSwap) PetscCall(PetscByteSwap(&nid, PETSC_ENUM, 1));
5209566063dSJacob Faibussowitsch     if (byteSwap) PetscCall(PetscByteSwap(xyz, PETSC_DOUBLE, 3));
5210598e1a2SLisandro Dalcin     nodes->id[n] = nid;
5227d5b9244SMatthew G. Knepley     for (t = 0; t < GMSH_MAX_TAGS; ++t) nodes->tag[n * GMSH_MAX_TAGS + t] = -1;
52311c56cb0SLisandro Dalcin   }
5243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
52511c56cb0SLisandro Dalcin }
52611c56cb0SLisandro Dalcin 
527de78e4feSLisandro Dalcin /* Gmsh elements can be of any dimension/co-dimension, so we need to traverse the
528de78e4feSLisandro Dalcin    file contents multiple times to figure out the true number of cells and facets
529de78e4feSLisandro Dalcin    in the given mesh. To make this more efficient we read the file contents only
530de78e4feSLisandro Dalcin    once and store them in memory, while determining the true number of cells. */
531d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements_v22(GmshFile *gmsh, GmshMesh *mesh)
532d71ae5a4SJacob Faibussowitsch {
533698a79b9SLisandro Dalcin   PetscViewer  viewer   = gmsh->viewer;
534698a79b9SLisandro Dalcin   PetscBool    binary   = gmsh->binary;
535698a79b9SLisandro Dalcin   PetscBool    byteSwap = gmsh->byteSwap;
536de78e4feSLisandro Dalcin   char         line[PETSC_MAX_PATH_LEN];
5370598e1a2SLisandro Dalcin   int          i, c, p, num, ibuf[1 + 4 + 1000], snum;
5380598e1a2SLisandro Dalcin   int          cellType, numElem, numVerts, numNodes, numTags;
539df032b82SMatthew G. Knepley   GmshElement *elements;
5400598e1a2SLisandro Dalcin   PetscInt    *nodeMap = gmsh->nodeMap;
541df032b82SMatthew G. Knepley 
542df032b82SMatthew G. Knepley   PetscFunctionBegin;
5439566063dSJacob Faibussowitsch   PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING));
544698a79b9SLisandro Dalcin   snum = sscanf(line, "%d", &num);
54508401ef6SPierre Jolivet   PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
5469566063dSJacob Faibussowitsch   PetscCall(GmshElementsCreate(num, &elements));
5470598e1a2SLisandro Dalcin   mesh->numElems = num;
5480598e1a2SLisandro Dalcin   mesh->elements = elements;
549698a79b9SLisandro Dalcin   for (c = 0; c < num;) {
5509566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM));
5519566063dSJacob Faibussowitsch     if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, 3));
5520598e1a2SLisandro Dalcin 
5530598e1a2SLisandro Dalcin     cellType = binary ? ibuf[0] : ibuf[1];
5540598e1a2SLisandro Dalcin     numElem  = binary ? ibuf[1] : 1;
555df032b82SMatthew G. Knepley     numTags  = ibuf[2];
5560598e1a2SLisandro Dalcin 
5579566063dSJacob Faibussowitsch     PetscCall(GmshCellTypeCheck(cellType));
5580598e1a2SLisandro Dalcin     numVerts = GmshCellMap[cellType].numVerts;
5590598e1a2SLisandro Dalcin     numNodes = GmshCellMap[cellType].numNodes;
5600598e1a2SLisandro Dalcin 
561df032b82SMatthew G. Knepley     for (i = 0; i < numElem; ++i, ++c) {
5620598e1a2SLisandro Dalcin       GmshElement *element = elements + c;
5630598e1a2SLisandro Dalcin       const int    off = binary ? 0 : 1, nint = 1 + numTags + numNodes - off;
5640598e1a2SLisandro Dalcin       const int   *id = ibuf, *nodes = ibuf + 1 + numTags, *tags = ibuf + 1;
5659566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, ibuf + off, nint, NULL, PETSC_ENUM));
5669566063dSJacob Faibussowitsch       if (byteSwap) PetscCall(PetscByteSwap(ibuf + off, PETSC_ENUM, nint));
5670598e1a2SLisandro Dalcin       element->id       = id[0];
5680598e1a2SLisandro Dalcin       element->dim      = GmshCellMap[cellType].dim;
5690598e1a2SLisandro Dalcin       element->cellType = cellType;
5700598e1a2SLisandro Dalcin       element->numVerts = numVerts;
5710598e1a2SLisandro Dalcin       element->numNodes = numNodes;
5727d5b9244SMatthew G. Knepley       element->numTags  = PetscMin(numTags, GMSH_MAX_TAGS);
5739566063dSJacob Faibussowitsch       PetscCall(PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes));
5740598e1a2SLisandro Dalcin       for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]];
5750598e1a2SLisandro Dalcin       for (p = 0; p < element->numTags; p++) element->tags[p] = tags[p];
576df032b82SMatthew G. Knepley     }
577df032b82SMatthew G. Knepley   }
5783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
579df032b82SMatthew G. Knepley }
5807d282ae0SMichael Lange 
581de78e4feSLisandro Dalcin /*
582de78e4feSLisandro Dalcin $Entities
583de78e4feSLisandro Dalcin   numPoints(unsigned long) numCurves(unsigned long)
584de78e4feSLisandro Dalcin     numSurfaces(unsigned long) numVolumes(unsigned long)
585de78e4feSLisandro Dalcin   // points
586de78e4feSLisandro Dalcin   tag(int) boxMinX(double) boxMinY(double) boxMinZ(double)
587de78e4feSLisandro Dalcin     boxMaxX(double) boxMaxY(double) boxMaxZ(double)
588de78e4feSLisandro Dalcin     numPhysicals(unsigned long) phyisicalTag[...](int)
589de78e4feSLisandro Dalcin   ...
590de78e4feSLisandro Dalcin   // curves
591de78e4feSLisandro Dalcin   tag(int) boxMinX(double) boxMinY(double) boxMinZ(double)
592de78e4feSLisandro Dalcin      boxMaxX(double) boxMaxY(double) boxMaxZ(double)
593de78e4feSLisandro Dalcin      numPhysicals(unsigned long) physicalTag[...](int)
594de78e4feSLisandro Dalcin      numBREPVert(unsigned long) tagBREPVert[...](int)
595de78e4feSLisandro Dalcin   ...
596de78e4feSLisandro Dalcin   // surfaces
597de78e4feSLisandro Dalcin   tag(int) boxMinX(double) boxMinY(double) boxMinZ(double)
598de78e4feSLisandro Dalcin     boxMaxX(double) boxMaxY(double) boxMaxZ(double)
599de78e4feSLisandro Dalcin     numPhysicals(unsigned long) physicalTag[...](int)
600de78e4feSLisandro Dalcin     numBREPCurve(unsigned long) tagBREPCurve[...](int)
601de78e4feSLisandro Dalcin   ...
602de78e4feSLisandro Dalcin   // volumes
603de78e4feSLisandro Dalcin   tag(int) boxMinX(double) boxMinY(double) boxMinZ(double)
604de78e4feSLisandro Dalcin     boxMaxX(double) boxMaxY(double) boxMaxZ(double)
605de78e4feSLisandro Dalcin     numPhysicals(unsigned long) physicalTag[...](int)
606de78e4feSLisandro Dalcin     numBREPSurfaces(unsigned long) tagBREPSurfaces[...](int)
607de78e4feSLisandro Dalcin   ...
608de78e4feSLisandro Dalcin $EndEntities
609de78e4feSLisandro Dalcin */
610d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEntities_v40(GmshFile *gmsh, GmshMesh *mesh)
611d71ae5a4SJacob Faibussowitsch {
612698a79b9SLisandro Dalcin   PetscViewer viewer   = gmsh->viewer;
613698a79b9SLisandro Dalcin   PetscBool   byteSwap = gmsh->byteSwap;
614698a79b9SLisandro Dalcin   long        index, num, lbuf[4];
615730356f6SLisandro Dalcin   int         dim, eid, numTags, *ibuf, t;
616698a79b9SLisandro Dalcin   PetscInt    count[4], i;
617a5ba3d71SLisandro Dalcin   GmshEntity *entity = NULL;
618de78e4feSLisandro Dalcin 
619de78e4feSLisandro Dalcin   PetscFunctionBegin;
6209566063dSJacob Faibussowitsch   PetscCall(PetscViewerRead(viewer, lbuf, 4, NULL, PETSC_LONG));
6219566063dSJacob Faibussowitsch   if (byteSwap) PetscCall(PetscByteSwap(lbuf, PETSC_LONG, 4));
622698a79b9SLisandro Dalcin   for (i = 0; i < 4; ++i) count[i] = lbuf[i];
6239566063dSJacob Faibussowitsch   PetscCall(GmshEntitiesCreate(count, &mesh->entities));
624de78e4feSLisandro Dalcin   for (dim = 0; dim < 4; ++dim) {
625730356f6SLisandro Dalcin     for (index = 0; index < count[dim]; ++index) {
6269566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, &eid, 1, NULL, PETSC_ENUM));
6279566063dSJacob Faibussowitsch       if (byteSwap) PetscCall(PetscByteSwap(&eid, PETSC_ENUM, 1));
6289566063dSJacob Faibussowitsch       PetscCall(GmshEntitiesAdd(mesh->entities, (PetscInt)index, dim, eid, &entity));
6299566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, entity->bbox, 6, NULL, PETSC_DOUBLE));
6309566063dSJacob Faibussowitsch       if (byteSwap) PetscCall(PetscByteSwap(entity->bbox, PETSC_DOUBLE, 6));
6319566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, &num, 1, NULL, PETSC_LONG));
6329566063dSJacob Faibussowitsch       if (byteSwap) PetscCall(PetscByteSwap(&num, PETSC_LONG, 1));
6339566063dSJacob Faibussowitsch       PetscCall(GmshBufferGet(gmsh, num, sizeof(int), &ibuf));
6349566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, ibuf, num, NULL, PETSC_ENUM));
6359566063dSJacob Faibussowitsch       if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, num));
6367d5b9244SMatthew G. Knepley       entity->numTags = numTags = (int)PetscMin(num, GMSH_MAX_TAGS);
637de78e4feSLisandro Dalcin       for (t = 0; t < numTags; ++t) entity->tags[t] = ibuf[t];
638de78e4feSLisandro Dalcin       if (dim == 0) continue;
6399566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, &num, 1, NULL, PETSC_LONG));
6409566063dSJacob Faibussowitsch       if (byteSwap) PetscCall(PetscByteSwap(&num, PETSC_LONG, 1));
6419566063dSJacob Faibussowitsch       PetscCall(GmshBufferGet(gmsh, num, sizeof(int), &ibuf));
6429566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, ibuf, num, NULL, PETSC_ENUM));
6439566063dSJacob Faibussowitsch       if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, num));
644de78e4feSLisandro Dalcin     }
645de78e4feSLisandro Dalcin   }
6463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
647de78e4feSLisandro Dalcin }
648de78e4feSLisandro Dalcin 
649de78e4feSLisandro Dalcin /*
650de78e4feSLisandro Dalcin $Nodes
651de78e4feSLisandro Dalcin   numEntityBlocks(unsigned long) numNodes(unsigned long)
652de78e4feSLisandro Dalcin   tagEntity(int) dimEntity(int) typeNode(int) numNodes(unsigned long)
653de78e4feSLisandro Dalcin     tag(int) x(double) y(double) z(double)
654de78e4feSLisandro Dalcin     ...
655de78e4feSLisandro Dalcin   ...
656de78e4feSLisandro Dalcin $EndNodes
657de78e4feSLisandro Dalcin */
658d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes_v40(GmshFile *gmsh, GmshMesh *mesh)
659d71ae5a4SJacob Faibussowitsch {
660698a79b9SLisandro Dalcin   PetscViewer viewer   = gmsh->viewer;
661698a79b9SLisandro Dalcin   PetscBool   byteSwap = gmsh->byteSwap;
6627d5b9244SMatthew G. Knepley   long        block, node, n, t, numEntityBlocks, numTotalNodes, numNodes;
663de78e4feSLisandro Dalcin   int         info[3], nid;
6640598e1a2SLisandro Dalcin   GmshNodes  *nodes;
665de78e4feSLisandro Dalcin 
666de78e4feSLisandro Dalcin   PetscFunctionBegin;
6679566063dSJacob Faibussowitsch   PetscCall(PetscViewerRead(viewer, &numEntityBlocks, 1, NULL, PETSC_LONG));
6689566063dSJacob Faibussowitsch   if (byteSwap) PetscCall(PetscByteSwap(&numEntityBlocks, PETSC_LONG, 1));
6699566063dSJacob Faibussowitsch   PetscCall(PetscViewerRead(viewer, &numTotalNodes, 1, NULL, PETSC_LONG));
6709566063dSJacob Faibussowitsch   if (byteSwap) PetscCall(PetscByteSwap(&numTotalNodes, PETSC_LONG, 1));
6719566063dSJacob Faibussowitsch   PetscCall(GmshNodesCreate(numTotalNodes, &nodes));
6720598e1a2SLisandro Dalcin   mesh->numNodes = numTotalNodes;
6730598e1a2SLisandro Dalcin   mesh->nodelist = nodes;
6740598e1a2SLisandro Dalcin   for (n = 0, block = 0; block < numEntityBlocks; ++block) {
6759566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, info, 3, NULL, PETSC_ENUM));
6769566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, &numNodes, 1, NULL, PETSC_LONG));
6779566063dSJacob Faibussowitsch     if (byteSwap) PetscCall(PetscByteSwap(&numNodes, PETSC_LONG, 1));
678698a79b9SLisandro Dalcin     if (gmsh->binary) {
679277f51e8SBarry Smith       size_t nbytes = sizeof(int) + 3 * sizeof(double);
680da81f932SPierre Jolivet       char  *cbuf   = NULL; /* dummy value to prevent warning from compiler about possible uninitialized value */
6819566063dSJacob Faibussowitsch       PetscCall(GmshBufferGet(gmsh, numNodes, nbytes, &cbuf));
6829566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, cbuf, numNodes * nbytes, NULL, PETSC_CHAR));
6830598e1a2SLisandro Dalcin       for (node = 0; node < numNodes; ++node, ++n) {
684de78e4feSLisandro Dalcin         char   *cnid = cbuf + node * nbytes, *cxyz = cnid + sizeof(int);
6850598e1a2SLisandro Dalcin         double *xyz = nodes->xyz + n * 3;
6869566063dSJacob Faibussowitsch         if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(cnid, PETSC_ENUM, 1));
6879566063dSJacob Faibussowitsch         if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(cxyz, PETSC_DOUBLE, 3));
6889566063dSJacob Faibussowitsch         PetscCall(PetscMemcpy(&nid, cnid, sizeof(int)));
6899566063dSJacob Faibussowitsch         PetscCall(PetscMemcpy(xyz, cxyz, 3 * sizeof(double)));
6909566063dSJacob Faibussowitsch         if (byteSwap) PetscCall(PetscByteSwap(&nid, PETSC_ENUM, 1));
6919566063dSJacob Faibussowitsch         if (byteSwap) PetscCall(PetscByteSwap(xyz, PETSC_DOUBLE, 3));
6920598e1a2SLisandro Dalcin         nodes->id[n] = nid;
6937d5b9244SMatthew G. Knepley         for (t = 0; t < GMSH_MAX_TAGS; ++t) nodes->tag[n * GMSH_MAX_TAGS + t] = -1;
694de78e4feSLisandro Dalcin       }
695de78e4feSLisandro Dalcin     } else {
6960598e1a2SLisandro Dalcin       for (node = 0; node < numNodes; ++node, ++n) {
6970598e1a2SLisandro Dalcin         double *xyz = nodes->xyz + n * 3;
6989566063dSJacob Faibussowitsch         PetscCall(PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM));
6999566063dSJacob Faibussowitsch         PetscCall(PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE));
7009566063dSJacob Faibussowitsch         if (byteSwap) PetscCall(PetscByteSwap(&nid, PETSC_ENUM, 1));
7019566063dSJacob Faibussowitsch         if (byteSwap) PetscCall(PetscByteSwap(xyz, PETSC_DOUBLE, 3));
7020598e1a2SLisandro Dalcin         nodes->id[n] = nid;
7037d5b9244SMatthew G. Knepley         for (t = 0; t < GMSH_MAX_TAGS; ++t) nodes->tag[n * GMSH_MAX_TAGS + t] = -1;
704de78e4feSLisandro Dalcin       }
705de78e4feSLisandro Dalcin     }
706de78e4feSLisandro Dalcin   }
7073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
708de78e4feSLisandro Dalcin }
709de78e4feSLisandro Dalcin 
710de78e4feSLisandro Dalcin /*
711de78e4feSLisandro Dalcin $Elements
712de78e4feSLisandro Dalcin   numEntityBlocks(unsigned long) numElements(unsigned long)
713de78e4feSLisandro Dalcin   tagEntity(int) dimEntity(int) typeEle(int) numElements(unsigned long)
714de78e4feSLisandro Dalcin     tag(int) numVert[...](int)
715de78e4feSLisandro Dalcin     ...
716de78e4feSLisandro Dalcin   ...
717de78e4feSLisandro Dalcin $EndElements
718de78e4feSLisandro Dalcin */
719d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements_v40(GmshFile *gmsh, GmshMesh *mesh)
720d71ae5a4SJacob Faibussowitsch {
721698a79b9SLisandro Dalcin   PetscViewer  viewer   = gmsh->viewer;
722698a79b9SLisandro Dalcin   PetscBool    byteSwap = gmsh->byteSwap;
723de78e4feSLisandro Dalcin   long         c, block, numEntityBlocks, numTotalElements, elem, numElements;
724de78e4feSLisandro Dalcin   int          p, info[3], *ibuf = NULL;
7250598e1a2SLisandro Dalcin   int          eid, dim, cellType, numVerts, numNodes, numTags;
726a5ba3d71SLisandro Dalcin   GmshEntity  *entity = NULL;
727de78e4feSLisandro Dalcin   GmshElement *elements;
7280598e1a2SLisandro Dalcin   PetscInt    *nodeMap = gmsh->nodeMap;
729de78e4feSLisandro Dalcin 
730de78e4feSLisandro Dalcin   PetscFunctionBegin;
7319566063dSJacob Faibussowitsch   PetscCall(PetscViewerRead(viewer, &numEntityBlocks, 1, NULL, PETSC_LONG));
7329566063dSJacob Faibussowitsch   if (byteSwap) PetscCall(PetscByteSwap(&numEntityBlocks, PETSC_LONG, 1));
7339566063dSJacob Faibussowitsch   PetscCall(PetscViewerRead(viewer, &numTotalElements, 1, NULL, PETSC_LONG));
7349566063dSJacob Faibussowitsch   if (byteSwap) PetscCall(PetscByteSwap(&numTotalElements, PETSC_LONG, 1));
7359566063dSJacob Faibussowitsch   PetscCall(GmshElementsCreate(numTotalElements, &elements));
7360598e1a2SLisandro Dalcin   mesh->numElems = numTotalElements;
7370598e1a2SLisandro Dalcin   mesh->elements = elements;
738de78e4feSLisandro Dalcin   for (c = 0, block = 0; block < numEntityBlocks; ++block) {
7399566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, info, 3, NULL, PETSC_ENUM));
7409566063dSJacob Faibussowitsch     if (byteSwap) PetscCall(PetscByteSwap(info, PETSC_ENUM, 3));
7419371c9d4SSatish Balay     eid      = info[0];
7429371c9d4SSatish Balay     dim      = info[1];
7439371c9d4SSatish Balay     cellType = info[2];
7449566063dSJacob Faibussowitsch     PetscCall(GmshEntitiesGet(mesh->entities, dim, eid, &entity));
7459566063dSJacob Faibussowitsch     PetscCall(GmshCellTypeCheck(cellType));
7460598e1a2SLisandro Dalcin     numVerts = GmshCellMap[cellType].numVerts;
7470598e1a2SLisandro Dalcin     numNodes = GmshCellMap[cellType].numNodes;
748730356f6SLisandro Dalcin     numTags  = entity->numTags;
7499566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, &numElements, 1, NULL, PETSC_LONG));
7509566063dSJacob Faibussowitsch     if (byteSwap) PetscCall(PetscByteSwap(&numElements, PETSC_LONG, 1));
7519566063dSJacob Faibussowitsch     PetscCall(GmshBufferGet(gmsh, (1 + numNodes) * numElements, sizeof(int), &ibuf));
7529566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, ibuf, (1 + numNodes) * numElements, NULL, PETSC_ENUM));
7539566063dSJacob Faibussowitsch     if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, (1 + numNodes) * numElements));
754de78e4feSLisandro Dalcin     for (elem = 0; elem < numElements; ++elem, ++c) {
755de78e4feSLisandro Dalcin       GmshElement *element = elements + c;
7560598e1a2SLisandro Dalcin       const int   *id = ibuf + elem * (1 + numNodes), *nodes = id + 1;
7570598e1a2SLisandro Dalcin       element->id       = id[0];
758de78e4feSLisandro Dalcin       element->dim      = dim;
759de78e4feSLisandro Dalcin       element->cellType = cellType;
7600598e1a2SLisandro Dalcin       element->numVerts = numVerts;
761de78e4feSLisandro Dalcin       element->numNodes = numNodes;
762de78e4feSLisandro Dalcin       element->numTags  = numTags;
7639566063dSJacob Faibussowitsch       PetscCall(PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes));
7640598e1a2SLisandro Dalcin       for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]];
7650598e1a2SLisandro Dalcin       for (p = 0; p < element->numTags; p++) element->tags[p] = entity->tags[p];
766de78e4feSLisandro Dalcin     }
767de78e4feSLisandro Dalcin   }
7683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
769698a79b9SLisandro Dalcin }
770698a79b9SLisandro Dalcin 
771d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPeriodic_v40(GmshFile *gmsh, PetscInt periodicMap[])
772d71ae5a4SJacob Faibussowitsch {
773698a79b9SLisandro Dalcin   PetscViewer viewer     = gmsh->viewer;
774698a79b9SLisandro Dalcin   int         fileFormat = gmsh->fileFormat;
775698a79b9SLisandro Dalcin   PetscBool   binary     = gmsh->binary;
776698a79b9SLisandro Dalcin   PetscBool   byteSwap   = gmsh->byteSwap;
777698a79b9SLisandro Dalcin   int         numPeriodic, snum, i;
778698a79b9SLisandro Dalcin   char        line[PETSC_MAX_PATH_LEN];
7790598e1a2SLisandro Dalcin   PetscInt   *nodeMap = gmsh->nodeMap;
780698a79b9SLisandro Dalcin 
781698a79b9SLisandro Dalcin   PetscFunctionBegin;
782698a79b9SLisandro Dalcin   if (fileFormat == 22 || !binary) {
7839566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING));
784698a79b9SLisandro Dalcin     snum = sscanf(line, "%d", &numPeriodic);
78508401ef6SPierre Jolivet     PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
786698a79b9SLisandro Dalcin   } else {
7879566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, &numPeriodic, 1, NULL, PETSC_ENUM));
7889566063dSJacob Faibussowitsch     if (byteSwap) PetscCall(PetscByteSwap(&numPeriodic, PETSC_ENUM, 1));
789698a79b9SLisandro Dalcin   }
790698a79b9SLisandro Dalcin   for (i = 0; i < numPeriodic; i++) {
7919dddd249SSatish Balay     int    ibuf[3], correspondingDim = -1, correspondingTag = -1, primaryTag = -1, correspondingNode, primaryNode;
792698a79b9SLisandro Dalcin     long   j, nNodes;
793698a79b9SLisandro Dalcin     double affine[16];
794698a79b9SLisandro Dalcin 
795698a79b9SLisandro Dalcin     if (fileFormat == 22 || !binary) {
7969566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, line, 3, NULL, PETSC_STRING));
7979dddd249SSatish Balay       snum = sscanf(line, "%d %d %d", &correspondingDim, &correspondingTag, &primaryTag);
79808401ef6SPierre Jolivet       PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
799698a79b9SLisandro Dalcin     } else {
8009566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM));
8019566063dSJacob Faibussowitsch       if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, 3));
8029371c9d4SSatish Balay       correspondingDim = ibuf[0];
8039371c9d4SSatish Balay       correspondingTag = ibuf[1];
8049371c9d4SSatish Balay       primaryTag       = ibuf[2];
805698a79b9SLisandro Dalcin     }
8069371c9d4SSatish Balay     (void)correspondingDim;
8079371c9d4SSatish Balay     (void)correspondingTag;
8089371c9d4SSatish Balay     (void)primaryTag; /* unused */
809698a79b9SLisandro Dalcin 
810698a79b9SLisandro Dalcin     if (fileFormat == 22 || !binary) {
8119566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING));
812698a79b9SLisandro Dalcin       snum = sscanf(line, "%ld", &nNodes);
8134c500f23SPierre Jolivet       if (snum != 1) { /* discard transformation and try again */
8149566063dSJacob Faibussowitsch         PetscCall(PetscViewerRead(viewer, line, -PETSC_MAX_PATH_LEN, NULL, PETSC_STRING));
8159566063dSJacob Faibussowitsch         PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING));
816698a79b9SLisandro Dalcin         snum = sscanf(line, "%ld", &nNodes);
81708401ef6SPierre Jolivet         PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
818698a79b9SLisandro Dalcin       }
819698a79b9SLisandro Dalcin     } else {
8209566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, &nNodes, 1, NULL, PETSC_LONG));
8219566063dSJacob Faibussowitsch       if (byteSwap) PetscCall(PetscByteSwap(&nNodes, PETSC_LONG, 1));
8224c500f23SPierre Jolivet       if (nNodes == -1) { /* discard transformation and try again */
8239566063dSJacob Faibussowitsch         PetscCall(PetscViewerRead(viewer, affine, 16, NULL, PETSC_DOUBLE));
8249566063dSJacob Faibussowitsch         PetscCall(PetscViewerRead(viewer, &nNodes, 1, NULL, PETSC_LONG));
8259566063dSJacob Faibussowitsch         if (byteSwap) PetscCall(PetscByteSwap(&nNodes, PETSC_LONG, 1));
826698a79b9SLisandro Dalcin       }
827698a79b9SLisandro Dalcin     }
828698a79b9SLisandro Dalcin 
829698a79b9SLisandro Dalcin     for (j = 0; j < nNodes; j++) {
830698a79b9SLisandro Dalcin       if (fileFormat == 22 || !binary) {
8319566063dSJacob Faibussowitsch         PetscCall(PetscViewerRead(viewer, line, 2, NULL, PETSC_STRING));
8329dddd249SSatish Balay         snum = sscanf(line, "%d %d", &correspondingNode, &primaryNode);
83308401ef6SPierre Jolivet         PetscCheck(snum == 2, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
834698a79b9SLisandro Dalcin       } else {
8359566063dSJacob Faibussowitsch         PetscCall(PetscViewerRead(viewer, ibuf, 2, NULL, PETSC_ENUM));
8369566063dSJacob Faibussowitsch         if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, 2));
8379371c9d4SSatish Balay         correspondingNode = ibuf[0];
8389371c9d4SSatish Balay         primaryNode       = ibuf[1];
839698a79b9SLisandro Dalcin       }
8409dddd249SSatish Balay       correspondingNode              = (int)nodeMap[correspondingNode];
8419dddd249SSatish Balay       primaryNode                    = (int)nodeMap[primaryNode];
8429dddd249SSatish Balay       periodicMap[correspondingNode] = primaryNode;
843698a79b9SLisandro Dalcin     }
844698a79b9SLisandro Dalcin   }
8453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
846698a79b9SLisandro Dalcin }
847698a79b9SLisandro Dalcin 
8480598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
849698a79b9SLisandro Dalcin $Entities
850698a79b9SLisandro Dalcin   numPoints(size_t) numCurves(size_t)
851698a79b9SLisandro Dalcin     numSurfaces(size_t) numVolumes(size_t)
852698a79b9SLisandro Dalcin   pointTag(int) X(double) Y(double) Z(double)
853698a79b9SLisandro Dalcin     numPhysicalTags(size_t) physicalTag(int) ...
854698a79b9SLisandro Dalcin   ...
855698a79b9SLisandro Dalcin   curveTag(int) minX(double) minY(double) minZ(double)
856698a79b9SLisandro Dalcin     maxX(double) maxY(double) maxZ(double)
857698a79b9SLisandro Dalcin     numPhysicalTags(size_t) physicalTag(int) ...
858698a79b9SLisandro Dalcin     numBoundingPoints(size_t) pointTag(int) ...
859698a79b9SLisandro Dalcin   ...
860698a79b9SLisandro Dalcin   surfaceTag(int) minX(double) minY(double) minZ(double)
861698a79b9SLisandro Dalcin     maxX(double) maxY(double) maxZ(double)
862698a79b9SLisandro Dalcin     numPhysicalTags(size_t) physicalTag(int) ...
863698a79b9SLisandro Dalcin     numBoundingCurves(size_t) curveTag(int) ...
864698a79b9SLisandro Dalcin   ...
865698a79b9SLisandro Dalcin   volumeTag(int) minX(double) minY(double) minZ(double)
866698a79b9SLisandro Dalcin     maxX(double) maxY(double) maxZ(double)
867698a79b9SLisandro Dalcin     numPhysicalTags(size_t) physicalTag(int) ...
868698a79b9SLisandro Dalcin     numBoundngSurfaces(size_t) surfaceTag(int) ...
869698a79b9SLisandro Dalcin   ...
870698a79b9SLisandro Dalcin $EndEntities
871698a79b9SLisandro Dalcin */
872d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEntities_v41(GmshFile *gmsh, GmshMesh *mesh)
873d71ae5a4SJacob Faibussowitsch {
874698a79b9SLisandro Dalcin   PetscInt    count[4], index, numTags, i;
875698a79b9SLisandro Dalcin   int         dim, eid, *tags = NULL;
876698a79b9SLisandro Dalcin   GmshEntity *entity = NULL;
877698a79b9SLisandro Dalcin 
878698a79b9SLisandro Dalcin   PetscFunctionBegin;
8799566063dSJacob Faibussowitsch   PetscCall(GmshReadSize(gmsh, count, 4));
8809566063dSJacob Faibussowitsch   PetscCall(GmshEntitiesCreate(count, &mesh->entities));
881698a79b9SLisandro Dalcin   for (dim = 0; dim < 4; ++dim) {
882698a79b9SLisandro Dalcin     for (index = 0; index < count[dim]; ++index) {
8839566063dSJacob Faibussowitsch       PetscCall(GmshReadInt(gmsh, &eid, 1));
8849566063dSJacob Faibussowitsch       PetscCall(GmshEntitiesAdd(mesh->entities, (PetscInt)index, dim, eid, &entity));
8859566063dSJacob Faibussowitsch       PetscCall(GmshReadDouble(gmsh, entity->bbox, (dim == 0) ? 3 : 6));
8869566063dSJacob Faibussowitsch       PetscCall(GmshReadSize(gmsh, &numTags, 1));
8879566063dSJacob Faibussowitsch       PetscCall(GmshBufferGet(gmsh, numTags, sizeof(int), &tags));
8889566063dSJacob Faibussowitsch       PetscCall(GmshReadInt(gmsh, tags, numTags));
8899c0edc59SMatthew G. Knepley       PetscCheck(numTags <= GMSH_MAX_TAGS, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PETSc currently supports up to %" PetscInt_FMT " tags per entity, not %" PetscInt_FMT, (PetscInt)GMSH_MAX_TAGS, numTags);
8907d5b9244SMatthew G. Knepley       entity->numTags = numTags;
891698a79b9SLisandro Dalcin       for (i = 0; i < entity->numTags; ++i) entity->tags[i] = tags[i];
892698a79b9SLisandro Dalcin       if (dim == 0) continue;
8939566063dSJacob Faibussowitsch       PetscCall(GmshReadSize(gmsh, &numTags, 1));
8949566063dSJacob Faibussowitsch       PetscCall(GmshBufferGet(gmsh, numTags, sizeof(int), &tags));
8959566063dSJacob Faibussowitsch       PetscCall(GmshReadInt(gmsh, tags, numTags));
89681a1af93SMatthew G. Knepley       /* Currently, we do not save the ids for the bounding entities */
897698a79b9SLisandro Dalcin     }
898698a79b9SLisandro Dalcin   }
8993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
900698a79b9SLisandro Dalcin }
901698a79b9SLisandro Dalcin 
90233a088b6SMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
903698a79b9SLisandro Dalcin $Nodes
904698a79b9SLisandro Dalcin   numEntityBlocks(size_t) numNodes(size_t)
905698a79b9SLisandro Dalcin     minNodeTag(size_t) maxNodeTag(size_t)
906698a79b9SLisandro Dalcin   entityDim(int) entityTag(int) parametric(int; 0 or 1) numNodesBlock(size_t)
907698a79b9SLisandro Dalcin     nodeTag(size_t)
908698a79b9SLisandro Dalcin     ...
909698a79b9SLisandro Dalcin     x(double) y(double) z(double)
910698a79b9SLisandro Dalcin        < u(double; if parametric and entityDim = 1 or entityDim = 2) >
911698a79b9SLisandro Dalcin        < v(double; if parametric and entityDim = 2) >
912698a79b9SLisandro Dalcin     ...
913698a79b9SLisandro Dalcin   ...
914698a79b9SLisandro Dalcin $EndNodes
915698a79b9SLisandro Dalcin */
916d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes_v41(GmshFile *gmsh, GmshMesh *mesh)
917d71ae5a4SJacob Faibussowitsch {
91881a1af93SMatthew G. Knepley   int         info[3], dim, eid, parametric;
9197d5b9244SMatthew G. Knepley   PetscInt    sizes[4], numEntityBlocks, numTags, t, numNodes, numNodesBlock = 0, block, node, n;
92081a1af93SMatthew G. Knepley   GmshEntity *entity = NULL;
9210598e1a2SLisandro Dalcin   GmshNodes  *nodes;
922698a79b9SLisandro Dalcin 
923698a79b9SLisandro Dalcin   PetscFunctionBegin;
9249566063dSJacob Faibussowitsch   PetscCall(GmshReadSize(gmsh, sizes, 4));
9259371c9d4SSatish Balay   numEntityBlocks = sizes[0];
9269371c9d4SSatish Balay   numNodes        = sizes[1];
9279566063dSJacob Faibussowitsch   PetscCall(GmshNodesCreate(numNodes, &nodes));
9280598e1a2SLisandro Dalcin   mesh->numNodes = numNodes;
9290598e1a2SLisandro Dalcin   mesh->nodelist = nodes;
930*e43c9757SMatthew G. Knepley   if (numEntityBlocks && !mesh->entities) PetscCall(PetscInfo(NULL, "File specifies %" PetscInt_FMT " entity blocks, but was missing the $Entities section\n", numEntityBlocks));
931698a79b9SLisandro Dalcin   for (block = 0, node = 0; block < numEntityBlocks; ++block, node += numNodesBlock) {
9329566063dSJacob Faibussowitsch     PetscCall(GmshReadInt(gmsh, info, 3));
9339371c9d4SSatish Balay     dim        = info[0];
9349371c9d4SSatish Balay     eid        = info[1];
9359371c9d4SSatish Balay     parametric = info[2];
936*e43c9757SMatthew G. Knepley     if (mesh->entities) PetscCall(GmshEntitiesGet(mesh->entities, dim, eid, &entity));
937*e43c9757SMatthew G. Knepley     numTags = entity ? entity->numTags : 0;
93881a1af93SMatthew G. Knepley     PetscCheck(!parametric, PETSC_COMM_SELF, PETSC_ERR_SUP, "Parametric coordinates not supported");
9399566063dSJacob Faibussowitsch     PetscCall(GmshReadSize(gmsh, &numNodesBlock, 1));
9409566063dSJacob Faibussowitsch     PetscCall(GmshReadSize(gmsh, nodes->id + node, numNodesBlock));
9419566063dSJacob Faibussowitsch     PetscCall(GmshReadDouble(gmsh, nodes->xyz + node * 3, numNodesBlock * 3));
9427d5b9244SMatthew G. Knepley     for (n = 0; n < numNodesBlock; ++n) {
9437d5b9244SMatthew G. Knepley       PetscInt *tags = &nodes->tag[node * GMSH_MAX_TAGS];
9447d5b9244SMatthew G. Knepley 
9457d5b9244SMatthew G. Knepley       for (t = 0; t < numTags; ++t) tags[n * GMSH_MAX_TAGS + t] = entity->tags[t];
9467d5b9244SMatthew G. Knepley       for (t = numTags; t < GMSH_MAX_TAGS; ++t) tags[n * GMSH_MAX_TAGS + t] = -1;
9477d5b9244SMatthew G. Knepley     }
948698a79b9SLisandro Dalcin   }
9490598e1a2SLisandro Dalcin   gmsh->nodeStart = sizes[2];
9500598e1a2SLisandro Dalcin   gmsh->nodeEnd   = sizes[3] + 1;
9513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
952698a79b9SLisandro Dalcin }
953698a79b9SLisandro Dalcin 
95433a088b6SMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
955698a79b9SLisandro Dalcin $Elements
956698a79b9SLisandro Dalcin   numEntityBlocks(size_t) numElements(size_t)
957698a79b9SLisandro Dalcin     minElementTag(size_t) maxElementTag(size_t)
958698a79b9SLisandro Dalcin   entityDim(int) entityTag(int) elementType(int; see below) numElementsBlock(size_t)
959698a79b9SLisandro Dalcin     elementTag(size_t) nodeTag(size_t) ...
960698a79b9SLisandro Dalcin     ...
961698a79b9SLisandro Dalcin   ...
962698a79b9SLisandro Dalcin $EndElements
963698a79b9SLisandro Dalcin */
964d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements_v41(GmshFile *gmsh, GmshMesh *mesh)
965d71ae5a4SJacob Faibussowitsch {
9660598e1a2SLisandro Dalcin   int          info[3], eid, dim, cellType;
9670598e1a2SLisandro Dalcin   PetscInt     sizes[4], *ibuf = NULL, numEntityBlocks, numElements, numBlockElements, numVerts, numNodes, numTags, block, elem, c, p;
968698a79b9SLisandro Dalcin   GmshEntity  *entity = NULL;
969698a79b9SLisandro Dalcin   GmshElement *elements;
9700598e1a2SLisandro Dalcin   PetscInt    *nodeMap = gmsh->nodeMap;
971698a79b9SLisandro Dalcin 
972698a79b9SLisandro Dalcin   PetscFunctionBegin;
9739566063dSJacob Faibussowitsch   PetscCall(GmshReadSize(gmsh, sizes, 4));
9749371c9d4SSatish Balay   numEntityBlocks = sizes[0];
9759371c9d4SSatish Balay   numElements     = sizes[1];
9769566063dSJacob Faibussowitsch   PetscCall(GmshElementsCreate(numElements, &elements));
9770598e1a2SLisandro Dalcin   mesh->numElems = numElements;
9780598e1a2SLisandro Dalcin   mesh->elements = elements;
979*e43c9757SMatthew G. Knepley   if (numEntityBlocks && !mesh->entities) PetscCall(PetscInfo(NULL, "File specifies %" PetscInt_FMT " entity blocks, but was missing the $Entities section\n", numEntityBlocks));
980698a79b9SLisandro Dalcin   for (c = 0, block = 0; block < numEntityBlocks; ++block) {
9819566063dSJacob Faibussowitsch     PetscCall(GmshReadInt(gmsh, info, 3));
9829371c9d4SSatish Balay     dim      = info[0];
9839371c9d4SSatish Balay     eid      = info[1];
9849371c9d4SSatish Balay     cellType = info[2];
985*e43c9757SMatthew G. Knepley     if (mesh->entities) PetscCall(GmshEntitiesGet(mesh->entities, dim, eid, &entity));
9869566063dSJacob Faibussowitsch     PetscCall(GmshCellTypeCheck(cellType));
9870598e1a2SLisandro Dalcin     numVerts = GmshCellMap[cellType].numVerts;
9880598e1a2SLisandro Dalcin     numNodes = GmshCellMap[cellType].numNodes;
989*e43c9757SMatthew G. Knepley     numTags  = entity ? entity->numTags : 0;
9909566063dSJacob Faibussowitsch     PetscCall(GmshReadSize(gmsh, &numBlockElements, 1));
9919566063dSJacob Faibussowitsch     PetscCall(GmshBufferGet(gmsh, (1 + numNodes) * numBlockElements, sizeof(PetscInt), &ibuf));
9929566063dSJacob Faibussowitsch     PetscCall(GmshReadSize(gmsh, ibuf, (1 + numNodes) * numBlockElements));
993698a79b9SLisandro Dalcin     for (elem = 0; elem < numBlockElements; ++elem, ++c) {
994698a79b9SLisandro Dalcin       GmshElement    *element = elements + c;
9950598e1a2SLisandro Dalcin       const PetscInt *id = ibuf + elem * (1 + numNodes), *nodes = id + 1;
996698a79b9SLisandro Dalcin       element->id       = id[0];
997698a79b9SLisandro Dalcin       element->dim      = dim;
998698a79b9SLisandro Dalcin       element->cellType = cellType;
9990598e1a2SLisandro Dalcin       element->numVerts = numVerts;
1000698a79b9SLisandro Dalcin       element->numNodes = numNodes;
1001698a79b9SLisandro Dalcin       element->numTags  = numTags;
10029566063dSJacob Faibussowitsch       PetscCall(PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes));
10030598e1a2SLisandro Dalcin       for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]];
10040598e1a2SLisandro Dalcin       for (p = 0; p < element->numTags; p++) element->tags[p] = entity->tags[p];
1005698a79b9SLisandro Dalcin     }
1006698a79b9SLisandro Dalcin   }
10073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1008698a79b9SLisandro Dalcin }
1009698a79b9SLisandro Dalcin 
10100598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
1011698a79b9SLisandro Dalcin $Periodic
1012698a79b9SLisandro Dalcin   numPeriodicLinks(size_t)
10139dddd249SSatish Balay   entityDim(int) entityTag(int) entityTagPrimary(int)
1014698a79b9SLisandro Dalcin   numAffine(size_t) value(double) ...
1015698a79b9SLisandro Dalcin   numCorrespondingNodes(size_t)
10169dddd249SSatish Balay     nodeTag(size_t) nodeTagPrimary(size_t)
1017698a79b9SLisandro Dalcin     ...
1018698a79b9SLisandro Dalcin   ...
1019698a79b9SLisandro Dalcin $EndPeriodic
1020698a79b9SLisandro Dalcin */
1021d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPeriodic_v41(GmshFile *gmsh, PetscInt periodicMap[])
1022d71ae5a4SJacob Faibussowitsch {
1023698a79b9SLisandro Dalcin   int       info[3];
1024698a79b9SLisandro Dalcin   double    dbuf[16];
10250598e1a2SLisandro Dalcin   PetscInt  numPeriodicLinks, numAffine, numCorrespondingNodes, *nodeTags = NULL, link, node;
10260598e1a2SLisandro Dalcin   PetscInt *nodeMap = gmsh->nodeMap;
1027698a79b9SLisandro Dalcin 
1028698a79b9SLisandro Dalcin   PetscFunctionBegin;
10299566063dSJacob Faibussowitsch   PetscCall(GmshReadSize(gmsh, &numPeriodicLinks, 1));
1030698a79b9SLisandro Dalcin   for (link = 0; link < numPeriodicLinks; ++link) {
10319566063dSJacob Faibussowitsch     PetscCall(GmshReadInt(gmsh, info, 3));
10329566063dSJacob Faibussowitsch     PetscCall(GmshReadSize(gmsh, &numAffine, 1));
10339566063dSJacob Faibussowitsch     PetscCall(GmshReadDouble(gmsh, dbuf, numAffine));
10349566063dSJacob Faibussowitsch     PetscCall(GmshReadSize(gmsh, &numCorrespondingNodes, 1));
10359566063dSJacob Faibussowitsch     PetscCall(GmshBufferGet(gmsh, numCorrespondingNodes, sizeof(PetscInt), &nodeTags));
10369566063dSJacob Faibussowitsch     PetscCall(GmshReadSize(gmsh, nodeTags, numCorrespondingNodes * 2));
1037698a79b9SLisandro Dalcin     for (node = 0; node < numCorrespondingNodes; ++node) {
10389dddd249SSatish Balay       PetscInt correspondingNode     = nodeMap[nodeTags[node * 2 + 0]];
10399dddd249SSatish Balay       PetscInt primaryNode           = nodeMap[nodeTags[node * 2 + 1]];
10409dddd249SSatish Balay       periodicMap[correspondingNode] = primaryNode;
1041698a79b9SLisandro Dalcin     }
1042698a79b9SLisandro Dalcin   }
10433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1044698a79b9SLisandro Dalcin }
1045698a79b9SLisandro Dalcin 
10460598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
1047d6689ca9SLisandro Dalcin $MeshFormat // same as MSH version 2
1048d6689ca9SLisandro Dalcin   version(ASCII double; currently 4.1)
1049d6689ca9SLisandro Dalcin   file-type(ASCII int; 0 for ASCII mode, 1 for binary mode)
1050d6689ca9SLisandro Dalcin   data-size(ASCII int; sizeof(size_t))
1051d6689ca9SLisandro Dalcin   < int with value one; only in binary mode, to detect endianness >
1052d6689ca9SLisandro Dalcin $EndMeshFormat
1053d6689ca9SLisandro Dalcin */
1054d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadMeshFormat(GmshFile *gmsh)
1055d71ae5a4SJacob Faibussowitsch {
1056698a79b9SLisandro Dalcin   char  line[PETSC_MAX_PATH_LEN];
1057698a79b9SLisandro Dalcin   int   snum, fileType, fileFormat, dataSize, checkEndian;
1058698a79b9SLisandro Dalcin   float version;
1059698a79b9SLisandro Dalcin 
1060698a79b9SLisandro Dalcin   PetscFunctionBegin;
10619566063dSJacob Faibussowitsch   PetscCall(GmshReadString(gmsh, line, 3));
1062698a79b9SLisandro Dalcin   snum       = sscanf(line, "%f %d %d", &version, &fileType, &dataSize);
1063a8d4e440SJunchao Zhang   fileFormat = (int)roundf(version * 10);
106408401ef6SPierre Jolivet   PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line);
1065a8d4e440SJunchao Zhang   PetscCheck(fileFormat >= 22, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at least 2.2", (double)version);
10661dca8a05SBarry Smith   PetscCheck((int)version != 3, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f not supported", (double)version);
1067a8d4e440SJunchao Zhang   PetscCheck(fileFormat <= 41, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at most 4.1", (double)version);
106808401ef6SPierre Jolivet   PetscCheck(!gmsh->binary || fileType, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Viewer is binary but Gmsh file is ASCII");
106908401ef6SPierre Jolivet   PetscCheck(gmsh->binary || !fileType, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Viewer is ASCII but Gmsh file is binary");
10701dca8a05SBarry 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);
10711dca8a05SBarry 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);
1072698a79b9SLisandro Dalcin   gmsh->fileFormat = fileFormat;
1073698a79b9SLisandro Dalcin   gmsh->dataSize   = dataSize;
1074698a79b9SLisandro Dalcin   gmsh->byteSwap   = PETSC_FALSE;
1075698a79b9SLisandro Dalcin   if (gmsh->binary) {
10769566063dSJacob Faibussowitsch     PetscCall(GmshReadInt(gmsh, &checkEndian, 1));
1077698a79b9SLisandro Dalcin     if (checkEndian != 1) {
10789566063dSJacob Faibussowitsch       PetscCall(PetscByteSwap(&checkEndian, PETSC_ENUM, 1));
107908401ef6SPierre Jolivet       PetscCheck(checkEndian == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to detect endianness in Gmsh file header: %s", line);
1080698a79b9SLisandro Dalcin       gmsh->byteSwap = PETSC_TRUE;
1081698a79b9SLisandro Dalcin     }
1082698a79b9SLisandro Dalcin   }
10833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1084698a79b9SLisandro Dalcin }
1085698a79b9SLisandro Dalcin 
10868749820aSMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
10878749820aSMatthew G. Knepley Neper: https://neper.info/ adds this section
10888749820aSMatthew G. Knepley 
10898749820aSMatthew G. Knepley $MeshVersion
10908749820aSMatthew G. Knepley   <major>.<minor>,<patch>
10918749820aSMatthew G. Knepley $EndMeshVersion
10928749820aSMatthew G. Knepley */
10938749820aSMatthew G. Knepley static PetscErrorCode GmshReadMeshVersion(GmshFile *gmsh)
10948749820aSMatthew G. Knepley {
10958749820aSMatthew G. Knepley   char line[PETSC_MAX_PATH_LEN];
10968749820aSMatthew G. Knepley   int  snum, major, minor, patch;
10978749820aSMatthew G. Knepley 
10988749820aSMatthew G. Knepley   PetscFunctionBegin;
10998749820aSMatthew G. Knepley   PetscCall(GmshReadString(gmsh, line, 1));
11008749820aSMatthew G. Knepley   snum = sscanf(line, "%d.%d.%d", &major, &minor, &patch);
11018749820aSMatthew G. Knepley   PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line);
11028749820aSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
11038749820aSMatthew G. Knepley }
11048749820aSMatthew G. Knepley 
11058749820aSMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
11068749820aSMatthew G. Knepley Neper: https://neper.info/ adds this section
11078749820aSMatthew G. Knepley 
11088749820aSMatthew G. Knepley $Domain
11098749820aSMatthew G. Knepley   <shape>
11108749820aSMatthew G. Knepley $EndDomain
11118749820aSMatthew G. Knepley */
11128749820aSMatthew G. Knepley static PetscErrorCode GmshReadMeshDomain(GmshFile *gmsh)
11138749820aSMatthew G. Knepley {
11148749820aSMatthew G. Knepley   char line[PETSC_MAX_PATH_LEN];
11158749820aSMatthew G. Knepley 
11168749820aSMatthew G. Knepley   PetscFunctionBegin;
11178749820aSMatthew G. Knepley   PetscCall(GmshReadString(gmsh, line, 1));
11188749820aSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
11198749820aSMatthew G. Knepley }
11208749820aSMatthew G. Knepley 
11211f643af3SLisandro Dalcin /*
11221f643af3SLisandro Dalcin PhysicalNames
11231f643af3SLisandro Dalcin   numPhysicalNames(ASCII int)
11241f643af3SLisandro Dalcin   dimension(ASCII int) physicalTag(ASCII int) "name"(127 characters max)
11251f643af3SLisandro Dalcin   ...
11261f643af3SLisandro Dalcin $EndPhysicalNames
11271f643af3SLisandro Dalcin */
1128d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPhysicalNames(GmshFile *gmsh, GmshMesh *mesh)
1129d71ae5a4SJacob Faibussowitsch {
1130bbcf679cSJacob Faibussowitsch   char line[PETSC_MAX_PATH_LEN], name[128 + 2], *p = NULL, *q = NULL, *r = NULL;
1131a45dabc8SMatthew G. Knepley   int  snum, region, dim, tag;
1132698a79b9SLisandro Dalcin 
1133698a79b9SLisandro Dalcin   PetscFunctionBegin;
11349566063dSJacob Faibussowitsch   PetscCall(GmshReadString(gmsh, line, 1));
1135a45dabc8SMatthew G. Knepley   snum             = sscanf(line, "%d", &region);
1136a45dabc8SMatthew G. Knepley   mesh->numRegions = region;
113708401ef6SPierre Jolivet   PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
113890d778b8SLisandro Dalcin   PetscCall(PetscMalloc3(mesh->numRegions, &mesh->regionDims, mesh->numRegions, &mesh->regionTags, mesh->numRegions, &mesh->regionNames));
1139a45dabc8SMatthew G. Knepley   for (region = 0; region < mesh->numRegions; ++region) {
11409566063dSJacob Faibussowitsch     PetscCall(GmshReadString(gmsh, line, 2));
11411f643af3SLisandro Dalcin     snum = sscanf(line, "%d %d", &dim, &tag);
114208401ef6SPierre Jolivet     PetscCheck(snum == 2, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
11439566063dSJacob Faibussowitsch     PetscCall(GmshReadString(gmsh, line, -(PetscInt)sizeof(line)));
11449566063dSJacob Faibussowitsch     PetscCall(PetscStrchr(line, '"', &p));
114528b400f6SJacob Faibussowitsch     PetscCheck(p, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
11469566063dSJacob Faibussowitsch     PetscCall(PetscStrrchr(line, '"', &q));
114708401ef6SPierre Jolivet     PetscCheck(q != p, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
11485f5cd6d5SMatthew G. Knepley     PetscCall(PetscStrrchr(line, ':', &r));
11495f5cd6d5SMatthew G. Knepley     if (p != r) q = r;
11509566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(name, p + 1, (size_t)(q - p - 1)));
115190d778b8SLisandro Dalcin     mesh->regionDims[region] = dim;
1152a45dabc8SMatthew G. Knepley     mesh->regionTags[region] = tag;
11539566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &mesh->regionNames[region]));
1154698a79b9SLisandro Dalcin   }
11553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1156de78e4feSLisandro Dalcin }
1157de78e4feSLisandro Dalcin 
1158d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEntities(GmshFile *gmsh, GmshMesh *mesh)
1159d71ae5a4SJacob Faibussowitsch {
11600598e1a2SLisandro Dalcin   PetscFunctionBegin;
11610598e1a2SLisandro Dalcin   switch (gmsh->fileFormat) {
1162d71ae5a4SJacob Faibussowitsch   case 41:
1163d71ae5a4SJacob Faibussowitsch     PetscCall(GmshReadEntities_v41(gmsh, mesh));
1164d71ae5a4SJacob Faibussowitsch     break;
1165d71ae5a4SJacob Faibussowitsch   default:
1166d71ae5a4SJacob Faibussowitsch     PetscCall(GmshReadEntities_v40(gmsh, mesh));
1167d71ae5a4SJacob Faibussowitsch     break;
116896ca5757SLisandro Dalcin   }
11693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11700598e1a2SLisandro Dalcin }
11710598e1a2SLisandro Dalcin 
1172d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes(GmshFile *gmsh, GmshMesh *mesh)
1173d71ae5a4SJacob Faibussowitsch {
11740598e1a2SLisandro Dalcin   PetscFunctionBegin;
11750598e1a2SLisandro Dalcin   switch (gmsh->fileFormat) {
1176d71ae5a4SJacob Faibussowitsch   case 41:
1177d71ae5a4SJacob Faibussowitsch     PetscCall(GmshReadNodes_v41(gmsh, mesh));
1178d71ae5a4SJacob Faibussowitsch     break;
1179d71ae5a4SJacob Faibussowitsch   case 40:
1180d71ae5a4SJacob Faibussowitsch     PetscCall(GmshReadNodes_v40(gmsh, mesh));
1181d71ae5a4SJacob Faibussowitsch     break;
1182d71ae5a4SJacob Faibussowitsch   default:
1183d71ae5a4SJacob Faibussowitsch     PetscCall(GmshReadNodes_v22(gmsh, mesh));
1184d71ae5a4SJacob Faibussowitsch     break;
11850598e1a2SLisandro Dalcin   }
11860598e1a2SLisandro Dalcin 
11870598e1a2SLisandro Dalcin   { /* Gmsh v2.2/v4.0 does not provide min/max node tags */
11880598e1a2SLisandro Dalcin     if (mesh->numNodes > 0 && gmsh->nodeEnd >= gmsh->nodeStart) {
11890598e1a2SLisandro Dalcin       PetscInt   tagMin = PETSC_MAX_INT, tagMax = PETSC_MIN_INT, n;
11900598e1a2SLisandro Dalcin       GmshNodes *nodes = mesh->nodelist;
11910598e1a2SLisandro Dalcin       for (n = 0; n < mesh->numNodes; ++n) {
11920598e1a2SLisandro Dalcin         const PetscInt tag = nodes->id[n];
11930598e1a2SLisandro Dalcin         tagMin             = PetscMin(tag, tagMin);
11940598e1a2SLisandro Dalcin         tagMax             = PetscMax(tag, tagMax);
11950598e1a2SLisandro Dalcin       }
11960598e1a2SLisandro Dalcin       gmsh->nodeStart = tagMin;
11970598e1a2SLisandro Dalcin       gmsh->nodeEnd   = tagMax + 1;
11980598e1a2SLisandro Dalcin     }
11990598e1a2SLisandro Dalcin   }
12000598e1a2SLisandro Dalcin 
12010598e1a2SLisandro Dalcin   { /* Support for sparse node tags */
12020598e1a2SLisandro Dalcin     PetscInt   n, t;
12030598e1a2SLisandro Dalcin     GmshNodes *nodes = mesh->nodelist;
12049566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(gmsh->nodeEnd - gmsh->nodeStart, &gmsh->nbuf));
12050598e1a2SLisandro Dalcin     for (t = 0; t < gmsh->nodeEnd - gmsh->nodeStart; ++t) gmsh->nbuf[t] = PETSC_MIN_INT;
12060598e1a2SLisandro Dalcin     gmsh->nodeMap = gmsh->nbuf - gmsh->nodeStart;
12070598e1a2SLisandro Dalcin     for (n = 0; n < mesh->numNodes; ++n) {
12080598e1a2SLisandro Dalcin       const PetscInt tag = nodes->id[n];
120963a3b9bcSJacob Faibussowitsch       PetscCheck(gmsh->nodeMap[tag] < 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Repeated node tag %" PetscInt_FMT, tag);
12100598e1a2SLisandro Dalcin       gmsh->nodeMap[tag] = n;
12110598e1a2SLisandro Dalcin     }
12120598e1a2SLisandro Dalcin   }
12133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12140598e1a2SLisandro Dalcin }
12150598e1a2SLisandro Dalcin 
1216d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements(GmshFile *gmsh, GmshMesh *mesh)
1217d71ae5a4SJacob Faibussowitsch {
12180598e1a2SLisandro Dalcin   PetscFunctionBegin;
12190598e1a2SLisandro Dalcin   switch (gmsh->fileFormat) {
1220d71ae5a4SJacob Faibussowitsch   case 41:
1221d71ae5a4SJacob Faibussowitsch     PetscCall(GmshReadElements_v41(gmsh, mesh));
1222d71ae5a4SJacob Faibussowitsch     break;
1223d71ae5a4SJacob Faibussowitsch   case 40:
1224d71ae5a4SJacob Faibussowitsch     PetscCall(GmshReadElements_v40(gmsh, mesh));
1225d71ae5a4SJacob Faibussowitsch     break;
1226d71ae5a4SJacob Faibussowitsch   default:
1227d71ae5a4SJacob Faibussowitsch     PetscCall(GmshReadElements_v22(gmsh, mesh));
1228d71ae5a4SJacob Faibussowitsch     break;
12290598e1a2SLisandro Dalcin   }
12300598e1a2SLisandro Dalcin 
12310598e1a2SLisandro Dalcin   { /* Reorder elements by codimension and polytope type */
12320598e1a2SLisandro Dalcin     PetscInt     ne       = mesh->numElems;
12330598e1a2SLisandro Dalcin     GmshElement *elements = mesh->elements;
1234066ea43fSLisandro Dalcin     PetscInt     keymap[GMSH_NUM_POLYTOPES], nk = 0;
1235066ea43fSLisandro Dalcin     PetscInt     offset[GMSH_NUM_POLYTOPES + 1], e, k;
12360598e1a2SLisandro Dalcin 
1237066ea43fSLisandro Dalcin     for (k = 0; k < GMSH_NUM_POLYTOPES; ++k) keymap[k] = PETSC_MIN_INT;
12389566063dSJacob Faibussowitsch     PetscCall(PetscMemzero(offset, sizeof(offset)));
12390598e1a2SLisandro Dalcin 
1240066ea43fSLisandro Dalcin     keymap[GMSH_TET] = nk++;
1241066ea43fSLisandro Dalcin     keymap[GMSH_HEX] = nk++;
1242066ea43fSLisandro Dalcin     keymap[GMSH_PRI] = nk++;
1243066ea43fSLisandro Dalcin     keymap[GMSH_PYR] = nk++;
1244066ea43fSLisandro Dalcin     keymap[GMSH_TRI] = nk++;
1245066ea43fSLisandro Dalcin     keymap[GMSH_QUA] = nk++;
1246066ea43fSLisandro Dalcin     keymap[GMSH_SEG] = nk++;
1247066ea43fSLisandro Dalcin     keymap[GMSH_VTX] = nk++;
12480598e1a2SLisandro Dalcin 
12499566063dSJacob Faibussowitsch     PetscCall(GmshElementsCreate(mesh->numElems, &mesh->elements));
12504ad8454bSPierre Jolivet #define key(eid) keymap[GmshCellMap[elements[eid].cellType].polytope]
12510598e1a2SLisandro Dalcin     for (e = 0; e < ne; ++e) offset[1 + key(e)]++;
12520598e1a2SLisandro Dalcin     for (k = 1; k < nk; ++k) offset[k] += offset[k - 1];
12530598e1a2SLisandro Dalcin     for (e = 0; e < ne; ++e) mesh->elements[offset[key(e)]++] = elements[e];
12540598e1a2SLisandro Dalcin #undef key
12559566063dSJacob Faibussowitsch     PetscCall(GmshElementsDestroy(&elements));
1256066ea43fSLisandro Dalcin   }
12570598e1a2SLisandro Dalcin 
1258066ea43fSLisandro Dalcin   { /* Mesh dimension and order */
1259066ea43fSLisandro Dalcin     GmshElement *elem = mesh->numElems ? mesh->elements : NULL;
1260066ea43fSLisandro Dalcin     mesh->dim         = elem ? GmshCellMap[elem->cellType].dim : 0;
1261066ea43fSLisandro Dalcin     mesh->order       = elem ? GmshCellMap[elem->cellType].order : 0;
12620598e1a2SLisandro Dalcin   }
12630598e1a2SLisandro Dalcin 
12640598e1a2SLisandro Dalcin   {
12650598e1a2SLisandro Dalcin     PetscBT  vtx;
12660598e1a2SLisandro Dalcin     PetscInt dim = mesh->dim, e, n, v;
12670598e1a2SLisandro Dalcin 
12689566063dSJacob Faibussowitsch     PetscCall(PetscBTCreate(mesh->numNodes, &vtx));
12690598e1a2SLisandro Dalcin 
12700598e1a2SLisandro Dalcin     /* Compute number of cells and set of vertices */
12710598e1a2SLisandro Dalcin     mesh->numCells = 0;
12720598e1a2SLisandro Dalcin     for (e = 0; e < mesh->numElems; ++e) {
12730598e1a2SLisandro Dalcin       GmshElement *elem = mesh->elements + e;
12740598e1a2SLisandro Dalcin       if (elem->dim == dim && dim > 0) mesh->numCells++;
127548a46eb9SPierre Jolivet       for (v = 0; v < elem->numVerts; v++) PetscCall(PetscBTSet(vtx, elem->nodes[v]));
12760598e1a2SLisandro Dalcin     }
12770598e1a2SLisandro Dalcin 
12780598e1a2SLisandro Dalcin     /* Compute numbering for vertices */
12790598e1a2SLisandro Dalcin     mesh->numVerts = 0;
12809566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(mesh->numNodes, &mesh->vertexMap));
12819371c9d4SSatish Balay     for (n = 0; n < mesh->numNodes; ++n) mesh->vertexMap[n] = PetscBTLookup(vtx, n) ? mesh->numVerts++ : PETSC_MIN_INT;
12820598e1a2SLisandro Dalcin 
12839566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&vtx));
12840598e1a2SLisandro Dalcin   }
12853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12860598e1a2SLisandro Dalcin }
12870598e1a2SLisandro Dalcin 
1288d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPeriodic(GmshFile *gmsh, GmshMesh *mesh)
1289d71ae5a4SJacob Faibussowitsch {
12900598e1a2SLisandro Dalcin   PetscInt n;
12910598e1a2SLisandro Dalcin 
12920598e1a2SLisandro Dalcin   PetscFunctionBegin;
12939566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(mesh->numNodes, &mesh->periodMap));
12940598e1a2SLisandro Dalcin   for (n = 0; n < mesh->numNodes; ++n) mesh->periodMap[n] = n;
12950598e1a2SLisandro Dalcin   switch (gmsh->fileFormat) {
1296d71ae5a4SJacob Faibussowitsch   case 41:
1297d71ae5a4SJacob Faibussowitsch     PetscCall(GmshReadPeriodic_v41(gmsh, mesh->periodMap));
1298d71ae5a4SJacob Faibussowitsch     break;
1299d71ae5a4SJacob Faibussowitsch   default:
1300d71ae5a4SJacob Faibussowitsch     PetscCall(GmshReadPeriodic_v40(gmsh, mesh->periodMap));
1301d71ae5a4SJacob Faibussowitsch     break;
13020598e1a2SLisandro Dalcin   }
13030598e1a2SLisandro Dalcin 
13049dddd249SSatish Balay   /* Find canonical primary nodes */
13050598e1a2SLisandro Dalcin   for (n = 0; n < mesh->numNodes; ++n)
13069371c9d4SSatish Balay     while (mesh->periodMap[n] != mesh->periodMap[mesh->periodMap[n]]) mesh->periodMap[n] = mesh->periodMap[mesh->periodMap[n]];
13070598e1a2SLisandro Dalcin 
13089dddd249SSatish Balay   /* Renumber vertices (filter out correspondings) */
13090598e1a2SLisandro Dalcin   mesh->numVerts = 0;
13100598e1a2SLisandro Dalcin   for (n = 0; n < mesh->numNodes; ++n)
13110598e1a2SLisandro Dalcin     if (mesh->vertexMap[n] >= 0)   /* is vertex */
13129dddd249SSatish Balay       if (mesh->periodMap[n] == n) /* is primary */
13130598e1a2SLisandro Dalcin         mesh->vertexMap[n] = mesh->numVerts++;
13140598e1a2SLisandro Dalcin   for (n = 0; n < mesh->numNodes; ++n)
13150598e1a2SLisandro Dalcin     if (mesh->vertexMap[n] >= 0)   /* is vertex */
13169dddd249SSatish Balay       if (mesh->periodMap[n] != n) /* is corresponding  */
13170598e1a2SLisandro Dalcin         mesh->vertexMap[n] = mesh->vertexMap[mesh->periodMap[n]];
13183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13190598e1a2SLisandro Dalcin }
13200598e1a2SLisandro Dalcin 
1321066ea43fSLisandro Dalcin #define DM_POLYTOPE_VERTEX DM_POLYTOPE_POINT
1322066ea43fSLisandro Dalcin static const DMPolytopeType DMPolytopeMap[] = {
1323066ea43fSLisandro Dalcin   /* GMSH_VTX */ DM_POLYTOPE_VERTEX,
1324066ea43fSLisandro Dalcin   /* GMSH_SEG */ DM_POLYTOPE_SEGMENT,
1325066ea43fSLisandro Dalcin   /* GMSH_TRI */ DM_POLYTOPE_TRIANGLE,
1326066ea43fSLisandro Dalcin   /* GMSH_QUA */ DM_POLYTOPE_QUADRILATERAL,
1327066ea43fSLisandro Dalcin   /* GMSH_TET */ DM_POLYTOPE_TETRAHEDRON,
1328066ea43fSLisandro Dalcin   /* GMSH_HEX */ DM_POLYTOPE_HEXAHEDRON,
1329066ea43fSLisandro Dalcin   /* GMSH_PRI */ DM_POLYTOPE_TRI_PRISM,
13309371c9d4SSatish Balay   /* GMSH_PYR */ DM_POLYTOPE_PYRAMID,       DM_POLYTOPE_UNKNOWN};
13310598e1a2SLisandro Dalcin 
1332d71ae5a4SJacob Faibussowitsch static inline DMPolytopeType DMPolytopeTypeFromGmsh(PetscInt cellType)
1333d71ae5a4SJacob Faibussowitsch {
1334066ea43fSLisandro Dalcin   return DMPolytopeMap[GmshCellMap[cellType].polytope];
1335066ea43fSLisandro Dalcin }
1336066ea43fSLisandro Dalcin 
1337d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshCreateFE(MPI_Comm comm, const char prefix[], PetscBool isSimplex, PetscBool continuity, PetscDTNodeType nodeType, PetscInt dim, PetscInt Nc, PetscInt k, PetscFE *fem)
1338d71ae5a4SJacob Faibussowitsch {
1339066ea43fSLisandro Dalcin   DM              K;
1340066ea43fSLisandro Dalcin   PetscSpace      P;
1341066ea43fSLisandro Dalcin   PetscDualSpace  Q;
1342066ea43fSLisandro Dalcin   PetscQuadrature q, fq;
1343066ea43fSLisandro Dalcin   PetscBool       isTensor = isSimplex ? PETSC_FALSE : PETSC_TRUE;
1344066ea43fSLisandro Dalcin   PetscBool       endpoint = PETSC_TRUE;
1345066ea43fSLisandro Dalcin   char            name[32];
1346066ea43fSLisandro Dalcin 
1347066ea43fSLisandro Dalcin   PetscFunctionBegin;
1348066ea43fSLisandro Dalcin   /* Create space */
13499566063dSJacob Faibussowitsch   PetscCall(PetscSpaceCreate(comm, &P));
13509566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSetType(P, PETSCSPACEPOLYNOMIAL));
13519566063dSJacob Faibussowitsch   PetscCall(PetscSpacePolynomialSetTensor(P, isTensor));
13529566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSetNumComponents(P, Nc));
13539566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSetNumVariables(P, dim));
13549566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSetDegree(P, k, PETSC_DETERMINE));
1355066ea43fSLisandro Dalcin   if (prefix) {
13569566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)P, prefix));
13579566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetFromOptions(P));
13589566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)P, NULL));
13599566063dSJacob Faibussowitsch     PetscCall(PetscSpaceGetDegree(P, &k, NULL));
1360066ea43fSLisandro Dalcin   }
13619566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSetUp(P));
1362066ea43fSLisandro Dalcin   /* Create dual space */
13639566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceCreate(comm, &Q));
13649566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSetType(Q, PETSCDUALSPACELAGRANGE));
13659566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceLagrangeSetTensor(Q, isTensor));
13669566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceLagrangeSetContinuity(Q, continuity));
13679566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceLagrangeSetNodeType(Q, nodeType, endpoint, 0));
13689566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSetNumComponents(Q, Nc));
13699566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSetOrder(Q, k));
13709566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateReferenceCell(PETSC_COMM_SELF, DMPolytopeTypeSimpleShape(dim, isSimplex), &K));
13719566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSetDM(Q, K));
13729566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&K));
1373066ea43fSLisandro Dalcin   if (prefix) {
13749566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)Q, prefix));
13759566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceSetFromOptions(Q));
13769566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)Q, NULL));
1377066ea43fSLisandro Dalcin   }
13789566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSetUp(Q));
1379066ea43fSLisandro Dalcin   /* Create quadrature */
1380066ea43fSLisandro Dalcin   if (isSimplex) {
13819566063dSJacob Faibussowitsch     PetscCall(PetscDTStroudConicalQuadrature(dim, 1, k + 1, -1, +1, &q));
13829566063dSJacob Faibussowitsch     PetscCall(PetscDTStroudConicalQuadrature(dim - 1, 1, k + 1, -1, +1, &fq));
1383066ea43fSLisandro Dalcin   } else {
13849566063dSJacob Faibussowitsch     PetscCall(PetscDTGaussTensorQuadrature(dim, 1, k + 1, -1, +1, &q));
13859566063dSJacob Faibussowitsch     PetscCall(PetscDTGaussTensorQuadrature(dim - 1, 1, k + 1, -1, +1, &fq));
1386066ea43fSLisandro Dalcin   }
1387066ea43fSLisandro Dalcin   /* Create finite element */
13889566063dSJacob Faibussowitsch   PetscCall(PetscFECreate(comm, fem));
13899566063dSJacob Faibussowitsch   PetscCall(PetscFESetType(*fem, PETSCFEBASIC));
13909566063dSJacob Faibussowitsch   PetscCall(PetscFESetNumComponents(*fem, Nc));
13919566063dSJacob Faibussowitsch   PetscCall(PetscFESetBasisSpace(*fem, P));
13929566063dSJacob Faibussowitsch   PetscCall(PetscFESetDualSpace(*fem, Q));
13939566063dSJacob Faibussowitsch   PetscCall(PetscFESetQuadrature(*fem, q));
13949566063dSJacob Faibussowitsch   PetscCall(PetscFESetFaceQuadrature(*fem, fq));
1395066ea43fSLisandro Dalcin   if (prefix) {
13969566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*fem, prefix));
13979566063dSJacob Faibussowitsch     PetscCall(PetscFESetFromOptions(*fem));
13989566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*fem, NULL));
1399066ea43fSLisandro Dalcin   }
14009566063dSJacob Faibussowitsch   PetscCall(PetscFESetUp(*fem));
1401066ea43fSLisandro Dalcin   /* Cleanup */
14029566063dSJacob Faibussowitsch   PetscCall(PetscSpaceDestroy(&P));
14039566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceDestroy(&Q));
14049566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureDestroy(&q));
14059566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureDestroy(&fq));
1406066ea43fSLisandro Dalcin   /* Set finite element name */
140763a3b9bcSJacob Faibussowitsch   PetscCall(PetscSNPrintf(name, sizeof(name), "%s%" PetscInt_FMT, isSimplex ? "P" : "Q", k));
14089566063dSJacob Faibussowitsch   PetscCall(PetscFESetName(*fem, name));
14093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
141096ca5757SLisandro Dalcin }
141196ca5757SLisandro Dalcin 
1412cc4c1da9SBarry Smith /*@
1413a1cb98faSBarry Smith   DMPlexCreateGmshFromFile - Create a `DMPLEX` mesh from a Gmsh file
1414d6689ca9SLisandro Dalcin 
1415a4e35b19SJacob Faibussowitsch   Input Parameters:
1416d6689ca9SLisandro Dalcin + comm        - The MPI communicator
1417d6689ca9SLisandro Dalcin . filename    - Name of the Gmsh file
1418d6689ca9SLisandro Dalcin - interpolate - Create faces and edges in the mesh
1419d6689ca9SLisandro Dalcin 
1420d6689ca9SLisandro Dalcin   Output Parameter:
1421a1cb98faSBarry Smith . dm - The `DM` object representing the mesh
1422d6689ca9SLisandro Dalcin 
1423d6689ca9SLisandro Dalcin   Level: beginner
1424d6689ca9SLisandro Dalcin 
14251cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()`
1426d6689ca9SLisandro Dalcin @*/
1427d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateGmshFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm)
1428d71ae5a4SJacob Faibussowitsch {
1429d6689ca9SLisandro Dalcin   PetscViewer     viewer;
1430d6689ca9SLisandro Dalcin   PetscMPIInt     rank;
1431d6689ca9SLisandro Dalcin   int             fileType;
1432d6689ca9SLisandro Dalcin   PetscViewerType vtype;
1433d6689ca9SLisandro Dalcin 
1434d6689ca9SLisandro Dalcin   PetscFunctionBegin;
14359566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1436d6689ca9SLisandro Dalcin 
1437d6689ca9SLisandro Dalcin   /* Determine Gmsh file type (ASCII or binary) from file header */
1438dd400576SPatrick Sanan   if (rank == 0) {
14390598e1a2SLisandro Dalcin     GmshFile gmsh[1];
1440d6689ca9SLisandro Dalcin     char     line[PETSC_MAX_PATH_LEN];
1441d6689ca9SLisandro Dalcin     int      snum;
1442d6689ca9SLisandro Dalcin     float    version;
1443a8d4e440SJunchao Zhang     int      fileFormat;
1444d6689ca9SLisandro Dalcin 
14459566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(gmsh, 1));
14469566063dSJacob Faibussowitsch     PetscCall(PetscViewerCreate(PETSC_COMM_SELF, &gmsh->viewer));
14479566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetType(gmsh->viewer, PETSCVIEWERASCII));
14489566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileSetMode(gmsh->viewer, FILE_MODE_READ));
14499566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileSetName(gmsh->viewer, filename));
1450d6689ca9SLisandro Dalcin     /* Read only the first two lines of the Gmsh file */
14519566063dSJacob Faibussowitsch     PetscCall(GmshReadSection(gmsh, line));
14529566063dSJacob Faibussowitsch     PetscCall(GmshExpect(gmsh, "$MeshFormat", line));
14539566063dSJacob Faibussowitsch     PetscCall(GmshReadString(gmsh, line, 2));
1454d6689ca9SLisandro Dalcin     snum       = sscanf(line, "%f %d", &version, &fileType);
1455a8d4e440SJunchao Zhang     fileFormat = (int)roundf(version * 10);
145608401ef6SPierre Jolivet     PetscCheck(snum == 2, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line);
1457a8d4e440SJunchao Zhang     PetscCheck(fileFormat >= 22, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at least 2.2", (double)version);
14581dca8a05SBarry Smith     PetscCheck((int)version != 3, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f not supported", (double)version);
1459a8d4e440SJunchao Zhang     PetscCheck(fileFormat <= 41, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at most 4.1", (double)version);
14609566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&gmsh->viewer));
1461d6689ca9SLisandro Dalcin   }
14629566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&fileType, 1, MPI_INT, 0, comm));
1463d6689ca9SLisandro Dalcin   vtype = (fileType == 0) ? PETSCVIEWERASCII : PETSCVIEWERBINARY;
1464d6689ca9SLisandro Dalcin 
1465d6689ca9SLisandro Dalcin   /* Create appropriate viewer and build plex */
14669566063dSJacob Faibussowitsch   PetscCall(PetscViewerCreate(comm, &viewer));
14679566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetType(viewer, vtype));
14689566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
14699566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetName(viewer, filename));
14709566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateGmsh(comm, viewer, interpolate, dm));
14719566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&viewer));
14723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1473d6689ca9SLisandro Dalcin }
1474d6689ca9SLisandro Dalcin 
1475331830f3SMatthew G. Knepley /*@
1476a1cb98faSBarry Smith   DMPlexCreateGmsh - Create a `DMPLEX` mesh from a Gmsh file viewer
1477331830f3SMatthew G. Knepley 
1478d083f849SBarry Smith   Collective
1479331830f3SMatthew G. Knepley 
1480331830f3SMatthew G. Knepley   Input Parameters:
1481331830f3SMatthew G. Knepley + comm        - The MPI communicator
1482a1cb98faSBarry Smith . viewer      - The `PetscViewer` associated with a Gmsh file
1483331830f3SMatthew G. Knepley - interpolate - Create faces and edges in the mesh
1484331830f3SMatthew G. Knepley 
1485331830f3SMatthew G. Knepley   Output Parameter:
1486a1cb98faSBarry Smith . dm - The `DM` object representing the mesh
1487331830f3SMatthew G. Knepley 
1488a1cb98faSBarry Smith   Options Database Keys:
1489df93260fSMatthew G. Knepley + -dm_plex_gmsh_hybrid        - Force triangular prisms to use tensor order
1490df93260fSMatthew G. Knepley . -dm_plex_gmsh_periodic      - Read Gmsh periodic section and construct a periodic Plex
1491df93260fSMatthew G. Knepley . -dm_plex_gmsh_highorder     - Generate high-order coordinates
1492df93260fSMatthew 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
14932b205333SMatthew G. Knepley . -dm_plex_gmsh_use_generic   - Generate generic labels, i.e. Cell Sets, Face Sets, etc.
1494df93260fSMatthew G. Knepley . -dm_plex_gmsh_use_regions   - Generate labels with region names
1495df93260fSMatthew G. Knepley . -dm_plex_gmsh_mark_vertices - Add vertices to generated labels
1496df93260fSMatthew G. Knepley . -dm_plex_gmsh_multiple_tags - Allow multiple tags for default labels
1497df93260fSMatthew G. Knepley - -dm_plex_gmsh_spacedim <d>  - Embedding space dimension, if different from topological dimension
1498df93260fSMatthew G. Knepley 
14991d27aa22SBarry Smith   Level: beginner
15001d27aa22SBarry Smith 
15011d27aa22SBarry Smith   Notes:
15021d27aa22SBarry Smith   The Gmsh file format is described in <http://gmsh.info/doc/texinfo/gmsh.html#MSH-file-format>
1503df93260fSMatthew G. Knepley 
15042b205333SMatthew G. Knepley   By default, the "Cell Sets", "Face Sets", and "Vertex Sets" labels are created, and only insert the first tag on a point. By using -dm_plex_gmsh_multiple_tags, all tags can be inserted. Alternatively, -dm_plex_gmsh_use_regions creates labels based on the region names from the PhysicalNames section, and all tags are used, but you can retain the generic labels using -dm_plex_gmsh_use_generic.
1505331830f3SMatthew G. Knepley 
15061cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`
1507331830f3SMatthew G. Knepley @*/
1508d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateGmsh(MPI_Comm comm, PetscViewer viewer, PetscBool interpolate, DM *dm)
1509d71ae5a4SJacob Faibussowitsch {
15100598e1a2SLisandro Dalcin   GmshMesh    *mesh          = NULL;
151111c56cb0SLisandro Dalcin   PetscViewer  parentviewer  = NULL;
15120598e1a2SLisandro Dalcin   PetscBT      periodicVerts = NULL;
1513eae3dc7dSJacob Faibussowitsch   PetscBT     *periodicCells = NULL;
15146858538eSMatthew G. Knepley   DM           cdm, cdmCell = NULL;
15156858538eSMatthew G. Knepley   PetscSection cs, csCell   = NULL;
15166858538eSMatthew G. Knepley   Vec          coordinates, coordinatesCell;
15170444adf6SMatthew G. Knepley   DMLabel      cellSets = NULL, faceSets = NULL, edgeSets = NULL, vertSets = NULL, marker = NULL, *regionSets;
15189db5b827SMatthew G. Knepley   PetscInt     dim = 0, coordDim = -1, order = 0, maxHeight = 0;
15199db5b827SMatthew G. Knepley   PetscInt     numNodes = 0, numElems = 0, numVerts = 0, numCells = 0, vStart, vEnd;
1520066ea43fSLisandro Dalcin   PetscInt     cell, cone[8], e, n, v, d;
15212b205333SMatthew G. Knepley   PetscBool    usegeneric = PETSC_TRUE, useregions = PETSC_FALSE, markvertices = PETSC_FALSE, multipleTags = PETSC_FALSE;
15222b205333SMatthew G. Knepley   PetscBool    flg, binary, hybrid = interpolate, periodic = PETSC_TRUE;
1523066ea43fSLisandro Dalcin   PetscBool    highOrder = PETSC_TRUE, highOrderSet, project = PETSC_FALSE;
1524066ea43fSLisandro Dalcin   PetscBool    isSimplex = PETSC_FALSE, isHybrid = PETSC_FALSE, hasTetra = PETSC_FALSE;
15250598e1a2SLisandro Dalcin   PetscMPIInt  rank;
1526331830f3SMatthew G. Knepley 
1527331830f3SMatthew G. Knepley   PetscFunctionBegin;
15289566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1529d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)viewer);
1530d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Gmsh options");
1531df93260fSMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_plex_gmsh_hybrid", "Force triangular prisms to use tensor order", "DMPlexCreateGmsh", hybrid, &hybrid, NULL));
15329566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_gmsh_periodic", "Read Gmsh periodic section", "DMPlexCreateGmsh", periodic, &periodic, NULL));
15339566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_gmsh_highorder", "Generate high-order coordinates", "DMPlexCreateGmsh", highOrder, &highOrder, &highOrderSet));
15349566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_gmsh_project", "Project high-order coordinates to a different space", "DMPlexCreateGmsh", project, &project, NULL));
15359566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_gmsh_use_regions", "Generate labels with region names", "DMPlexCreateGmsh", useregions, &useregions, NULL));
15362b205333SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_plex_gmsh_use_generic", "Generate generic labels, i.e. Cell Sets, Face Sets, etc", "DMPlexCreateGmsh", usegeneric, &usegeneric, &flg));
15372b205333SMatthew G. Knepley   if (!flg && useregions) usegeneric = PETSC_FALSE;
15389566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_gmsh_mark_vertices", "Add vertices to generated labels", "DMPlexCreateGmsh", markvertices, &markvertices, NULL));
1539df93260fSMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_plex_gmsh_multiple_tags", "Allow multiple tags for default labels", "DMPlexCreateGmsh", multipleTags, &multipleTags, NULL));
15409566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_gmsh_spacedim", "Embedding space dimension", "DMPlexCreateGmsh", coordDim, &coordDim, NULL, PETSC_DECIDE));
15419db5b827SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_localize_height", "Localize edges and faces in addition to cells", "", maxHeight, &maxHeight, NULL, 0));
1542d0609cedSBarry Smith   PetscOptionsHeadEnd();
1543d0609cedSBarry Smith   PetscOptionsEnd();
15440598e1a2SLisandro Dalcin 
15459566063dSJacob Faibussowitsch   PetscCall(GmshCellInfoSetUp());
154611c56cb0SLisandro Dalcin 
15479566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
15489566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
15499566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CreateGmsh, *dm, NULL, NULL, NULL));
155011c56cb0SLisandro Dalcin 
15519566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &binary));
155211c56cb0SLisandro Dalcin 
155311c56cb0SLisandro Dalcin   /* Binary viewers read on all ranks, get subviewer to read only in rank 0 */
15543b46f529SLisandro Dalcin   if (binary) {
155511c56cb0SLisandro Dalcin     parentviewer = viewer;
15569566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetSubViewer(parentviewer, PETSC_COMM_SELF, &viewer));
155711c56cb0SLisandro Dalcin   }
155811c56cb0SLisandro Dalcin 
1559dd400576SPatrick Sanan   if (rank == 0) {
15600598e1a2SLisandro Dalcin     GmshFile  gmsh[1];
1561698a79b9SLisandro Dalcin     char      line[PETSC_MAX_PATH_LEN];
1562698a79b9SLisandro Dalcin     PetscBool match;
1563331830f3SMatthew G. Knepley 
15649566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(gmsh, 1));
1565698a79b9SLisandro Dalcin     gmsh->viewer = viewer;
1566698a79b9SLisandro Dalcin     gmsh->binary = binary;
1567698a79b9SLisandro Dalcin 
15689566063dSJacob Faibussowitsch     PetscCall(GmshMeshCreate(&mesh));
15690598e1a2SLisandro Dalcin 
1570698a79b9SLisandro Dalcin     /* Read mesh format */
15719566063dSJacob Faibussowitsch     PetscCall(GmshReadSection(gmsh, line));
15729566063dSJacob Faibussowitsch     PetscCall(GmshExpect(gmsh, "$MeshFormat", line));
15739566063dSJacob Faibussowitsch     PetscCall(GmshReadMeshFormat(gmsh));
15749566063dSJacob Faibussowitsch     PetscCall(GmshReadEndSection(gmsh, "$EndMeshFormat", line));
157511c56cb0SLisandro Dalcin 
15768749820aSMatthew G. Knepley     /* OPTIONAL Read mesh version (Neper only) */
15779566063dSJacob Faibussowitsch     PetscCall(GmshReadSection(gmsh, line));
15788749820aSMatthew G. Knepley     PetscCall(GmshMatch(gmsh, "$MeshVersion", line, &match));
15798749820aSMatthew G. Knepley     if (match) {
15808749820aSMatthew G. Knepley       PetscCall(GmshExpect(gmsh, "$MeshVersion", line));
15818749820aSMatthew G. Knepley       PetscCall(GmshReadMeshVersion(gmsh));
15828749820aSMatthew G. Knepley       PetscCall(GmshReadEndSection(gmsh, "$EndMeshVersion", line));
15838749820aSMatthew G. Knepley       /* Initial read for entity section */
15848749820aSMatthew G. Knepley       PetscCall(GmshReadSection(gmsh, line));
15858749820aSMatthew G. Knepley     }
15868749820aSMatthew G. Knepley 
15878749820aSMatthew G. Knepley     /* OPTIONAL Read mesh domain (Neper only) */
15888749820aSMatthew G. Knepley     PetscCall(GmshMatch(gmsh, "$Domain", line, &match));
15898749820aSMatthew G. Knepley     if (match) {
15908749820aSMatthew G. Knepley       PetscCall(GmshExpect(gmsh, "$Domain", line));
15918749820aSMatthew G. Knepley       PetscCall(GmshReadMeshDomain(gmsh));
15928749820aSMatthew G. Knepley       PetscCall(GmshReadEndSection(gmsh, "$EndDomain", line));
15938749820aSMatthew G. Knepley       /* Initial read for entity section */
15948749820aSMatthew G. Knepley       PetscCall(GmshReadSection(gmsh, line));
15958749820aSMatthew G. Knepley     }
15968749820aSMatthew G. Knepley 
15978749820aSMatthew G. Knepley     /* OPTIONAL Read physical names */
15989566063dSJacob Faibussowitsch     PetscCall(GmshMatch(gmsh, "$PhysicalNames", line, &match));
1599dc0ede3bSMatthew G. Knepley     if (match) {
16009566063dSJacob Faibussowitsch       PetscCall(GmshExpect(gmsh, "$PhysicalNames", line));
16019566063dSJacob Faibussowitsch       PetscCall(GmshReadPhysicalNames(gmsh, mesh));
16029566063dSJacob Faibussowitsch       PetscCall(GmshReadEndSection(gmsh, "$EndPhysicalNames", line));
1603698a79b9SLisandro Dalcin       /* Initial read for entity section */
16049566063dSJacob Faibussowitsch       PetscCall(GmshReadSection(gmsh, line));
1605dc0ede3bSMatthew G. Knepley     }
160611c56cb0SLisandro Dalcin 
1607*e43c9757SMatthew G. Knepley     /* OPTIONAL Read entities */
1608698a79b9SLisandro Dalcin     if (gmsh->fileFormat >= 40) {
1609*e43c9757SMatthew G. Knepley       PetscCall(GmshMatch(gmsh, "$Entities", line, &match));
1610*e43c9757SMatthew G. Knepley       if (match) {
16119566063dSJacob Faibussowitsch         PetscCall(GmshExpect(gmsh, "$Entities", line));
16129566063dSJacob Faibussowitsch         PetscCall(GmshReadEntities(gmsh, mesh));
16139566063dSJacob Faibussowitsch         PetscCall(GmshReadEndSection(gmsh, "$EndEntities", line));
1614698a79b9SLisandro Dalcin         /* Initial read for nodes section */
16159566063dSJacob Faibussowitsch         PetscCall(GmshReadSection(gmsh, line));
1616de78e4feSLisandro Dalcin       }
1617*e43c9757SMatthew G. Knepley     }
1618de78e4feSLisandro Dalcin 
1619698a79b9SLisandro Dalcin     /* Read nodes */
16209566063dSJacob Faibussowitsch     PetscCall(GmshExpect(gmsh, "$Nodes", line));
16219566063dSJacob Faibussowitsch     PetscCall(GmshReadNodes(gmsh, mesh));
16229566063dSJacob Faibussowitsch     PetscCall(GmshReadEndSection(gmsh, "$EndNodes", line));
162311c56cb0SLisandro Dalcin 
1624698a79b9SLisandro Dalcin     /* Read elements */
16259566063dSJacob Faibussowitsch     PetscCall(GmshReadSection(gmsh, line));
16269566063dSJacob Faibussowitsch     PetscCall(GmshExpect(gmsh, "$Elements", line));
16279566063dSJacob Faibussowitsch     PetscCall(GmshReadElements(gmsh, mesh));
16289566063dSJacob Faibussowitsch     PetscCall(GmshReadEndSection(gmsh, "$EndElements", line));
1629de78e4feSLisandro Dalcin 
16300598e1a2SLisandro Dalcin     /* Read periodic section (OPTIONAL) */
1631698a79b9SLisandro Dalcin     if (periodic) {
16329566063dSJacob Faibussowitsch       PetscCall(GmshReadSection(gmsh, line));
16339566063dSJacob Faibussowitsch       PetscCall(GmshMatch(gmsh, "$Periodic", line, &periodic));
1634ef12879bSLisandro Dalcin     }
1635ef12879bSLisandro Dalcin     if (periodic) {
16369566063dSJacob Faibussowitsch       PetscCall(GmshExpect(gmsh, "$Periodic", line));
16379566063dSJacob Faibussowitsch       PetscCall(GmshReadPeriodic(gmsh, mesh));
16389566063dSJacob Faibussowitsch       PetscCall(GmshReadEndSection(gmsh, "$EndPeriodic", line));
1639698a79b9SLisandro Dalcin     }
1640698a79b9SLisandro Dalcin 
16419566063dSJacob Faibussowitsch     PetscCall(PetscFree(gmsh->wbuf));
16429566063dSJacob Faibussowitsch     PetscCall(PetscFree(gmsh->sbuf));
16439566063dSJacob Faibussowitsch     PetscCall(PetscFree(gmsh->nbuf));
16440598e1a2SLisandro Dalcin 
16450598e1a2SLisandro Dalcin     dim      = mesh->dim;
1646066ea43fSLisandro Dalcin     order    = mesh->order;
16470598e1a2SLisandro Dalcin     numNodes = mesh->numNodes;
16480598e1a2SLisandro Dalcin     numElems = mesh->numElems;
16490598e1a2SLisandro Dalcin     numVerts = mesh->numVerts;
16500598e1a2SLisandro Dalcin     numCells = mesh->numCells;
1651066ea43fSLisandro Dalcin 
1652066ea43fSLisandro Dalcin     {
1653066ea43fSLisandro Dalcin       GmshElement *elemA = mesh->numCells > 0 ? mesh->elements : NULL;
16548e3a54c0SPierre Jolivet       GmshElement *elemB = PetscSafePointerPlusOffset(elemA, mesh->numCells - 1);
1655066ea43fSLisandro Dalcin       int          ptA   = elemA ? GmshCellMap[elemA->cellType].polytope : -1;
1656066ea43fSLisandro Dalcin       int          ptB   = elemB ? GmshCellMap[elemB->cellType].polytope : -1;
1657066ea43fSLisandro Dalcin       isSimplex          = (ptA == GMSH_QUA || ptA == GMSH_HEX) ? PETSC_FALSE : PETSC_TRUE;
1658066ea43fSLisandro Dalcin       isHybrid           = (ptA == ptB) ? PETSC_FALSE : PETSC_TRUE;
1659066ea43fSLisandro Dalcin       hasTetra           = (ptA == GMSH_TET) ? PETSC_TRUE : PETSC_FALSE;
1660066ea43fSLisandro Dalcin     }
1661698a79b9SLisandro Dalcin   }
1662698a79b9SLisandro Dalcin 
166348a46eb9SPierre Jolivet   if (parentviewer) PetscCall(PetscViewerRestoreSubViewer(parentviewer, PETSC_COMM_SELF, &viewer));
1664698a79b9SLisandro Dalcin 
1665066ea43fSLisandro Dalcin   {
1666066ea43fSLisandro Dalcin     int buf[6];
1667698a79b9SLisandro Dalcin 
1668066ea43fSLisandro Dalcin     buf[0] = (int)dim;
1669066ea43fSLisandro Dalcin     buf[1] = (int)order;
1670066ea43fSLisandro Dalcin     buf[2] = periodic;
1671066ea43fSLisandro Dalcin     buf[3] = isSimplex;
1672066ea43fSLisandro Dalcin     buf[4] = isHybrid;
1673066ea43fSLisandro Dalcin     buf[5] = hasTetra;
1674066ea43fSLisandro Dalcin 
16759566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Bcast(buf, 6, MPI_INT, 0, comm));
1676066ea43fSLisandro Dalcin 
1677066ea43fSLisandro Dalcin     dim       = buf[0];
1678066ea43fSLisandro Dalcin     order     = buf[1];
1679066ea43fSLisandro Dalcin     periodic  = buf[2] ? PETSC_TRUE : PETSC_FALSE;
1680066ea43fSLisandro Dalcin     isSimplex = buf[3] ? PETSC_TRUE : PETSC_FALSE;
1681066ea43fSLisandro Dalcin     isHybrid  = buf[4] ? PETSC_TRUE : PETSC_FALSE;
1682066ea43fSLisandro Dalcin     hasTetra  = buf[5] ? PETSC_TRUE : PETSC_FALSE;
1683dea2a3c7SStefano Zampini   }
1684dea2a3c7SStefano Zampini 
1685066ea43fSLisandro Dalcin   if (!highOrderSet) highOrder = (order > 1) ? PETSC_TRUE : PETSC_FALSE;
168608401ef6SPierre Jolivet   PetscCheck(!highOrder || !isHybrid, comm, PETSC_ERR_SUP, "No support for discretization on hybrid meshes yet");
1687066ea43fSLisandro Dalcin 
16880598e1a2SLisandro Dalcin   /* We do not want this label automatically computed, instead we fill it here */
16899566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(*dm, "celltype"));
169011c56cb0SLisandro Dalcin 
1691a4bb7517SMichael Lange   /* Allocate the cell-vertex mesh */
16929566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(*dm, 0, numCells + numVerts));
16930598e1a2SLisandro Dalcin   for (cell = 0; cell < numCells; ++cell) {
16940598e1a2SLisandro Dalcin     GmshElement   *elem  = mesh->elements + cell;
16950598e1a2SLisandro Dalcin     DMPolytopeType ctype = DMPolytopeTypeFromGmsh(elem->cellType);
16960598e1a2SLisandro Dalcin     if (hybrid && hasTetra && ctype == DM_POLYTOPE_TRI_PRISM) ctype = DM_POLYTOPE_TRI_PRISM_TENSOR;
16979566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeSize(*dm, cell, elem->numVerts));
16989566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCellType(*dm, cell, ctype));
1699db397164SMichael Lange   }
170048a46eb9SPierre Jolivet   for (v = numCells; v < numCells + numVerts; ++v) PetscCall(DMPlexSetCellType(*dm, v, DM_POLYTOPE_POINT));
17019566063dSJacob Faibussowitsch   PetscCall(DMSetUp(*dm));
170296ca5757SLisandro Dalcin 
1703a4bb7517SMichael Lange   /* Add cell-vertex connections */
17040598e1a2SLisandro Dalcin   for (cell = 0; cell < numCells; ++cell) {
17050598e1a2SLisandro Dalcin     GmshElement *elem = mesh->elements + cell;
17060598e1a2SLisandro Dalcin     for (v = 0; v < elem->numVerts; ++v) {
17070598e1a2SLisandro Dalcin       const PetscInt nn = elem->nodes[v];
17080598e1a2SLisandro Dalcin       const PetscInt vv = mesh->vertexMap[nn];
17090598e1a2SLisandro Dalcin       cone[v]           = numCells + vv;
1710db397164SMichael Lange     }
17119566063dSJacob Faibussowitsch     PetscCall(DMPlexReorderCell(*dm, cell, cone));
17129566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCone(*dm, cell, cone));
1713a4bb7517SMichael Lange   }
171496ca5757SLisandro Dalcin 
17159566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
17169566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(*dm));
17179566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(*dm));
1718331830f3SMatthew G. Knepley   if (interpolate) {
17195fd9971aSMatthew G. Knepley     DM idm;
1720331830f3SMatthew G. Knepley 
17219566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
17229566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
1723331830f3SMatthew G. Knepley     *dm = idm;
1724331830f3SMatthew G. Knepley   }
17259db5b827SMatthew G. Knepley   PetscCall(DMPlexGetDepthStratum(*dm, 0, &vStart, &vEnd));
1726917266a4SLisandro Dalcin 
1727dd400576SPatrick Sanan   if (rank == 0) {
1728a45dabc8SMatthew G. Knepley     const PetscInt Nr = useregions ? mesh->numRegions : 0;
1729d1a54cefSMatthew G. Knepley 
17309566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(Nr, &regionSets));
17310598e1a2SLisandro Dalcin     for (cell = 0, e = 0; e < numElems; ++e) {
17320598e1a2SLisandro Dalcin       GmshElement *elem = mesh->elements + e;
17336e1dd89aSLawrence Mitchell 
17346e1dd89aSLawrence Mitchell       /* Create cell sets */
17350598e1a2SLisandro Dalcin       if (elem->dim == dim && dim > 0) {
17360598e1a2SLisandro Dalcin         if (elem->numTags > 0) {
1737df93260fSMatthew G. Knepley           PetscInt Nt = elem->numTags, t, r;
1738a45dabc8SMatthew G. Knepley 
1739df93260fSMatthew G. Knepley           for (t = 0; t < Nt; ++t) {
1740df93260fSMatthew G. Knepley             const PetscInt  tag     = elem->tags[t];
17412b205333SMatthew G. Knepley             const PetscBool generic = usegeneric && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE;
1742df93260fSMatthew G. Knepley 
1743df93260fSMatthew G. Knepley             if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &cellSets, "Cell Sets", cell, tag));
1744a45dabc8SMatthew G. Knepley             for (r = 0; r < Nr; ++r) {
1745df93260fSMatthew G. Knepley               if (mesh->regionDims[r] != dim) continue;
17469566063dSJacob Faibussowitsch               if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, &regionSets[r], mesh->regionNames[r], cell, tag));
1747a45dabc8SMatthew G. Knepley             }
17486e1dd89aSLawrence Mitchell           }
1749df93260fSMatthew G. Knepley         }
1750917266a4SLisandro Dalcin         cell++;
17516e1dd89aSLawrence Mitchell       }
17520c070f12SSander Arens 
17530598e1a2SLisandro Dalcin       /* Create face sets */
1754aec57b10SMatthew G. Knepley       if (elem->numTags && interpolate && elem->dim == dim - 1) {
17550598e1a2SLisandro Dalcin         PetscInt        joinSize;
17560598e1a2SLisandro Dalcin         const PetscInt *join = NULL;
17570444adf6SMatthew G. Knepley         PetscInt        Nt   = elem->numTags, pdepth;
1758a45dabc8SMatthew G. Knepley 
17590598e1a2SLisandro Dalcin         /* Find the relevant facet with vertex joins */
17600598e1a2SLisandro Dalcin         for (v = 0; v < elem->numVerts; ++v) {
17610598e1a2SLisandro Dalcin           const PetscInt nn = elem->nodes[v];
17620598e1a2SLisandro Dalcin           const PetscInt vv = mesh->vertexMap[nn];
17630598e1a2SLisandro Dalcin           cone[v]           = vStart + vv;
17640598e1a2SLisandro Dalcin         }
17659566063dSJacob Faibussowitsch         PetscCall(DMPlexGetFullJoin(*dm, elem->numVerts, cone, &joinSize, &join));
176663a3b9bcSJacob 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);
17670444adf6SMatthew G. Knepley         PetscCall(DMPlexGetPointDepth(*dm, join[0], &pdepth));
17680444adf6SMatthew 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);
17690444adf6SMatthew G. Knepley         for (PetscInt t = 0; t < Nt; ++t) {
17705ad74b4fSMatthew G. Knepley           const PetscInt  tag     = elem->tags[t];
17712b205333SMatthew G. Knepley           const PetscBool generic = usegeneric && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE;
17725ad74b4fSMatthew G. Knepley 
1773df93260fSMatthew G. Knepley           if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &faceSets, "Face Sets", join[0], tag));
17740444adf6SMatthew G. Knepley           for (PetscInt r = 0; r < Nr; ++r) {
1775df93260fSMatthew G. Knepley             if (mesh->regionDims[r] != dim - 1) continue;
17769566063dSJacob Faibussowitsch             if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, &regionSets[r], mesh->regionNames[r], join[0], tag));
1777a45dabc8SMatthew G. Knepley           }
17785ad74b4fSMatthew G. Knepley         }
17799566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreJoin(*dm, elem->numVerts, cone, &joinSize, &join));
17800598e1a2SLisandro Dalcin       }
17810598e1a2SLisandro Dalcin 
1782aec57b10SMatthew G. Knepley       /* Create edge sets */
1783aec57b10SMatthew G. Knepley       if (elem->numTags && interpolate && dim > 2 && elem->dim == 1) {
1784aec57b10SMatthew G. Knepley         PetscInt        joinSize;
1785aec57b10SMatthew G. Knepley         const PetscInt *join = NULL;
1786aec57b10SMatthew G. Knepley         PetscInt        Nt   = elem->numTags, t, r;
1787aec57b10SMatthew G. Knepley 
1788aec57b10SMatthew G. Knepley         /* Find the relevant edge with vertex joins */
1789aec57b10SMatthew G. Knepley         for (v = 0; v < elem->numVerts; ++v) {
1790aec57b10SMatthew G. Knepley           const PetscInt nn = elem->nodes[v];
1791aec57b10SMatthew G. Knepley           const PetscInt vv = mesh->vertexMap[nn];
1792aec57b10SMatthew G. Knepley           cone[v]           = vStart + vv;
1793aec57b10SMatthew G. Knepley         }
1794aec57b10SMatthew G. Knepley         PetscCall(DMPlexGetJoin(*dm, elem->numVerts, cone, &joinSize, &join));
1795aec57b10SMatthew 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);
1796aec57b10SMatthew G. Knepley         for (t = 0; t < Nt; ++t) {
1797aec57b10SMatthew G. Knepley           const PetscInt  tag     = elem->tags[t];
17982b205333SMatthew G. Knepley           const PetscBool generic = usegeneric && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE;
1799aec57b10SMatthew G. Knepley 
18000444adf6SMatthew G. Knepley           if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &edgeSets, "Edge Sets", join[0], tag));
1801aec57b10SMatthew G. Knepley           for (r = 0; r < Nr; ++r) {
1802aec57b10SMatthew G. Knepley             if (mesh->regionDims[r] != 1) continue;
1803aec57b10SMatthew G. Knepley             if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, &regionSets[r], mesh->regionNames[r], join[0], tag));
1804aec57b10SMatthew G. Knepley           }
1805aec57b10SMatthew G. Knepley         }
1806aec57b10SMatthew G. Knepley         PetscCall(DMPlexRestoreJoin(*dm, elem->numVerts, cone, &joinSize, &join));
1807aec57b10SMatthew G. Knepley       }
1808aec57b10SMatthew G. Knepley 
18090c070f12SSander Arens       /* Create vertex sets */
1810aec57b10SMatthew G. Knepley       if (elem->numTags && elem->dim == 0 && markvertices) {
18110598e1a2SLisandro Dalcin         const PetscInt nn  = elem->nodes[0];
18120598e1a2SLisandro Dalcin         const PetscInt vv  = mesh->vertexMap[nn];
1813a45dabc8SMatthew G. Knepley         const PetscInt tag = elem->tags[0];
1814a45dabc8SMatthew G. Knepley         PetscInt       r;
1815a45dabc8SMatthew G. Knepley 
18168a3d9825SMatthew G. Knepley         if (vv < 0) continue;
18172b205333SMatthew G. Knepley         if (usegeneric) PetscCall(DMSetLabelValue_Fast(*dm, &vertSets, "Vertex Sets", vStart + vv, tag));
181881a1af93SMatthew G. Knepley         for (r = 0; r < Nr; ++r) {
1819df93260fSMatthew G. Knepley           if (mesh->regionDims[r] != 0) continue;
18209566063dSJacob Faibussowitsch           if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, &regionSets[r], mesh->regionNames[r], vStart + vv, tag));
182181a1af93SMatthew G. Knepley         }
182281a1af93SMatthew G. Knepley       }
182381a1af93SMatthew G. Knepley     }
182481a1af93SMatthew G. Knepley     if (markvertices) {
182581a1af93SMatthew G. Knepley       for (v = 0; v < numNodes; ++v) {
182681a1af93SMatthew G. Knepley         const PetscInt  vv   = mesh->vertexMap[v];
18277d5b9244SMatthew G. Knepley         const PetscInt *tags = &mesh->nodelist->tag[v * GMSH_MAX_TAGS];
18287d5b9244SMatthew G. Knepley         PetscInt        r, t;
182981a1af93SMatthew G. Knepley 
18308a3d9825SMatthew G. Knepley         if (vv < 0) continue;
18317d5b9244SMatthew G. Knepley         for (t = 0; t < GMSH_MAX_TAGS; ++t) {
18327d5b9244SMatthew G. Knepley           const PetscInt  tag     = tags[t];
18332b205333SMatthew G. Knepley           const PetscBool generic = usegeneric && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE;
18347d5b9244SMatthew G. Knepley 
18357d5b9244SMatthew G. Knepley           if (tag == -1) continue;
1836df93260fSMatthew G. Knepley           if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &vertSets, "Vertex Sets", vStart + vv, tag));
1837a45dabc8SMatthew G. Knepley           for (r = 0; r < Nr; ++r) {
18389566063dSJacob Faibussowitsch             if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, &regionSets[r], mesh->regionNames[r], vStart + vv, tag));
18390598e1a2SLisandro Dalcin           }
18400598e1a2SLisandro Dalcin         }
18410598e1a2SLisandro Dalcin       }
18420598e1a2SLisandro Dalcin     }
18439566063dSJacob Faibussowitsch     PetscCall(PetscFree(regionSets));
1844a45dabc8SMatthew G. Knepley   }
18450598e1a2SLisandro Dalcin 
18460444adf6SMatthew G. Knepley   { /* Create Cell/Face/Edge/Vertex Sets labels at all processes */
18479371c9d4SSatish Balay     enum {
18480444adf6SMatthew G. Knepley       n = 5
18499371c9d4SSatish Balay     };
18507dd454faSLisandro Dalcin     PetscBool flag[n];
18517dd454faSLisandro Dalcin 
18527dd454faSLisandro Dalcin     flag[0] = cellSets ? PETSC_TRUE : PETSC_FALSE;
18537dd454faSLisandro Dalcin     flag[1] = faceSets ? PETSC_TRUE : PETSC_FALSE;
18540444adf6SMatthew G. Knepley     flag[2] = edgeSets ? PETSC_TRUE : PETSC_FALSE;
18550444adf6SMatthew G. Knepley     flag[3] = vertSets ? PETSC_TRUE : PETSC_FALSE;
18560444adf6SMatthew G. Knepley     flag[4] = marker ? PETSC_TRUE : PETSC_FALSE;
18579566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Bcast(flag, n, MPIU_BOOL, 0, comm));
18589566063dSJacob Faibussowitsch     if (flag[0]) PetscCall(DMCreateLabel(*dm, "Cell Sets"));
18599566063dSJacob Faibussowitsch     if (flag[1]) PetscCall(DMCreateLabel(*dm, "Face Sets"));
18600444adf6SMatthew G. Knepley     if (flag[2]) PetscCall(DMCreateLabel(*dm, "Edge Sets"));
18610444adf6SMatthew G. Knepley     if (flag[3]) PetscCall(DMCreateLabel(*dm, "Vertex Sets"));
18620444adf6SMatthew G. Knepley     if (flag[4]) PetscCall(DMCreateLabel(*dm, "marker"));
18637dd454faSLisandro Dalcin   }
18647dd454faSLisandro Dalcin 
18650598e1a2SLisandro Dalcin   if (periodic) {
18669566063dSJacob Faibussowitsch     PetscCall(PetscBTCreate(numVerts, &periodicVerts));
18670598e1a2SLisandro Dalcin     for (n = 0; n < numNodes; ++n) {
18680598e1a2SLisandro Dalcin       if (mesh->vertexMap[n] >= 0) {
18690598e1a2SLisandro Dalcin         if (PetscUnlikely(mesh->periodMap[n] != n)) {
18700598e1a2SLisandro Dalcin           PetscInt m = mesh->periodMap[n];
18719566063dSJacob Faibussowitsch           PetscCall(PetscBTSet(periodicVerts, mesh->vertexMap[n]));
18729566063dSJacob Faibussowitsch           PetscCall(PetscBTSet(periodicVerts, mesh->vertexMap[m]));
18730598e1a2SLisandro Dalcin         }
18740598e1a2SLisandro Dalcin       }
18750598e1a2SLisandro Dalcin     }
18769db5b827SMatthew G. Knepley     PetscCall(DMGetCoordinateDM(*dm, &cdm));
1877eae3dc7dSJacob Faibussowitsch     PetscCall(PetscMalloc1(maxHeight + 1, &periodicCells));
18789db5b827SMatthew G. Knepley     for (PetscInt h = 0; h <= maxHeight; ++h) {
18799db5b827SMatthew G. Knepley       PetscInt pStart, pEnd;
18809db5b827SMatthew G. Knepley 
18819db5b827SMatthew G. Knepley       PetscCall(DMPlexGetHeightStratum(*dm, h, &pStart, &pEnd));
18829db5b827SMatthew G. Knepley       PetscCall(PetscBTCreate(pEnd - pStart, &periodicCells[h]));
18839db5b827SMatthew G. Knepley       for (PetscInt p = pStart; p < pEnd; ++p) {
18849db5b827SMatthew G. Knepley         PetscInt *closure = NULL;
18859db5b827SMatthew G. Knepley         PetscInt  Ncl;
18869db5b827SMatthew G. Knepley 
18879db5b827SMatthew G. Knepley         PetscCall(DMPlexGetTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure));
18889db5b827SMatthew G. Knepley         for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) {
18899db5b827SMatthew G. Knepley           if (closure[cl] >= vStart && closure[cl] < vEnd) {
18909db5b827SMatthew G. Knepley             if (PetscUnlikely(PetscBTLookup(periodicVerts, closure[cl] - vStart))) {
18919db5b827SMatthew G. Knepley               PetscCall(PetscBTSet(periodicCells[h], p - pStart));
18929371c9d4SSatish Balay               break;
18930c070f12SSander Arens             }
18940c070f12SSander Arens           }
18950c070f12SSander Arens         }
18969db5b827SMatthew G. Knepley         PetscCall(DMPlexRestoreTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure));
18979db5b827SMatthew G. Knepley       }
18989db5b827SMatthew G. Knepley     }
189916ad7e67SMichael Lange   }
190016ad7e67SMichael Lange 
1901066ea43fSLisandro Dalcin   /* Setup coordinate DM */
19020598e1a2SLisandro Dalcin   if (coordDim < 0) coordDim = dim;
19039566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(*dm, coordDim));
19049566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(*dm, &cdm));
1905066ea43fSLisandro Dalcin   if (highOrder) {
1906066ea43fSLisandro Dalcin     PetscFE         fe;
1907066ea43fSLisandro Dalcin     PetscBool       continuity = periodic ? PETSC_FALSE : PETSC_TRUE;
1908066ea43fSLisandro Dalcin     PetscDTNodeType nodeType   = PETSCDTNODES_EQUISPACED;
1909066ea43fSLisandro Dalcin 
1910066ea43fSLisandro Dalcin     if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */
1911066ea43fSLisandro Dalcin 
19129566063dSJacob Faibussowitsch     PetscCall(GmshCreateFE(comm, NULL, isSimplex, continuity, nodeType, dim, coordDim, order, &fe));
19139566063dSJacob Faibussowitsch     PetscCall(PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_fe_view"));
19149566063dSJacob Faibussowitsch     PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)fe));
19159566063dSJacob Faibussowitsch     PetscCall(PetscFEDestroy(&fe));
19169566063dSJacob Faibussowitsch     PetscCall(DMCreateDS(cdm));
1917066ea43fSLisandro Dalcin   }
19186858538eSMatthew G. Knepley   if (periodic) {
19196858538eSMatthew G. Knepley     PetscCall(DMClone(cdm, &cdmCell));
19206858538eSMatthew G. Knepley     PetscCall(DMSetCellCoordinateDM(*dm, cdmCell));
19216858538eSMatthew G. Knepley   }
1922066ea43fSLisandro Dalcin 
1923066ea43fSLisandro Dalcin   /* Create coordinates */
1924066ea43fSLisandro Dalcin   if (highOrder) {
1925066ea43fSLisandro Dalcin     PetscInt     maxDof = GmshNumNodes_HEX(order) * coordDim;
1926066ea43fSLisandro Dalcin     double      *coords = mesh ? mesh->nodelist->xyz : NULL;
1927066ea43fSLisandro Dalcin     PetscSection section;
1928066ea43fSLisandro Dalcin     PetscScalar *cellCoords;
1929066ea43fSLisandro Dalcin 
19309566063dSJacob Faibussowitsch     PetscCall(DMSetLocalSection(cdm, NULL));
19316858538eSMatthew G. Knepley     PetscCall(DMGetLocalSection(cdm, &cs));
19326858538eSMatthew G. Knepley     PetscCall(PetscSectionClone(cs, &section));
19339566063dSJacob Faibussowitsch     PetscCall(DMPlexSetClosurePermutationTensor(cdm, 0, section)); /* XXX Implement DMPlexSetClosurePermutationLexicographic() */
1934066ea43fSLisandro Dalcin 
19359566063dSJacob Faibussowitsch     PetscCall(DMCreateLocalVector(cdm, &coordinates));
19369566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(maxDof, &cellCoords));
1937066ea43fSLisandro Dalcin     for (cell = 0; cell < numCells; ++cell) {
1938066ea43fSLisandro Dalcin       GmshElement *elem     = mesh->elements + cell;
1939066ea43fSLisandro Dalcin       const int   *lexorder = GmshCellMap[elem->cellType].lexorder();
1940b9bf55e5SMatthew G. Knepley       int          s        = 0;
1941066ea43fSLisandro Dalcin       for (n = 0; n < elem->numNodes; ++n) {
1942b9bf55e5SMatthew G. Knepley         while (lexorder[n + s] < 0) ++s;
1943b9bf55e5SMatthew G. Knepley         const PetscInt node = elem->nodes[lexorder[n + s]];
1944b9bf55e5SMatthew G. Knepley         for (d = 0; d < coordDim; ++d) cellCoords[(n + s) * coordDim + d] = (PetscReal)coords[node * 3 + d];
1945b9bf55e5SMatthew G. Knepley       }
1946b9bf55e5SMatthew G. Knepley       if (s) {
1947b9bf55e5SMatthew G. Knepley         /* For the coordinate mapping we weight vertices by -1/4 and edges by 1/2, which we get from Q_2 interpolation */
1948b9bf55e5SMatthew G. Knepley         PetscReal quaCenterWeights[9] = {-0.25, 0.5, -0.25, 0.5, 0.0, 0.5, -0.25, 0.5, -0.25};
1949b9bf55e5SMatthew G. Knepley         /* For the coordinate mapping we weight vertices by -1/4 and edges by 1/2, which we get from Q_2 interpolation */
19509371c9d4SSatish 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};
19519371c9d4SSatish 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};
19529371c9d4SSatish 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};
19539371c9d4SSatish 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};
19549371c9d4SSatish 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};
19559371c9d4SSatish 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};
19569371c9d4SSatish 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};
1957b9bf55e5SMatthew G. Knepley         PetscReal  *sdWeights2[9]        = {NULL, NULL, NULL, NULL, quaCenterWeights, NULL, NULL, NULL, NULL};
19589371c9d4SSatish Balay         PetscReal  *sdWeights3[27]       = {NULL, NULL, NULL, NULL, hexBottomWeights, NULL, NULL, NULL, NULL, NULL, hexFrontWeights, NULL, hexLeftWeights, hexCenterWeights, hexRightWeights, NULL, hexBackWeights, NULL,
1959b9bf55e5SMatthew G. Knepley                                             NULL, NULL, NULL, NULL, hexTopWeights,    NULL, NULL, NULL, NULL};
1960b9bf55e5SMatthew G. Knepley         PetscReal **sdWeights[4]         = {NULL, NULL, sdWeights2, sdWeights3};
1961b9bf55e5SMatthew G. Knepley 
1962b9bf55e5SMatthew G. Knepley         /* Missing entries in serendipity cell, only works for 8-node quad and 20-node hex */
1963b9bf55e5SMatthew G. Knepley         for (n = 0; n < elem->numNodes + s; ++n) {
1964b9bf55e5SMatthew G. Knepley           if (lexorder[n] >= 0) continue;
1965b9bf55e5SMatthew G. Knepley           for (d = 0; d < coordDim; ++d) cellCoords[n * coordDim + d] = 0.0;
1966b9bf55e5SMatthew G. Knepley           for (int bn = 0; bn < elem->numNodes + s; ++bn) {
1967b9bf55e5SMatthew G. Knepley             if (lexorder[bn] < 0) continue;
1968b9bf55e5SMatthew G. Knepley             const PetscReal *weights = sdWeights[coordDim][n];
1969b9bf55e5SMatthew G. Knepley             const PetscInt   bnode   = elem->nodes[lexorder[bn]];
1970b9bf55e5SMatthew G. Knepley             for (d = 0; d < coordDim; ++d) cellCoords[n * coordDim + d] += weights[bn] * (PetscReal)coords[bnode * 3 + d];
1971b9bf55e5SMatthew G. Knepley           }
1972b9bf55e5SMatthew G. Knepley         }
1973066ea43fSLisandro Dalcin       }
19749566063dSJacob Faibussowitsch       PetscCall(DMPlexVecSetClosure(cdm, section, coordinates, cell, cellCoords, INSERT_VALUES));
1975066ea43fSLisandro Dalcin     }
19769566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&section));
19779566063dSJacob Faibussowitsch     PetscCall(PetscFree(cellCoords));
1978066ea43fSLisandro Dalcin   } else {
1979066ea43fSLisandro Dalcin     PetscInt    *nodeMap;
1980066ea43fSLisandro Dalcin     double      *coords = mesh ? mesh->nodelist->xyz : NULL;
1981066ea43fSLisandro Dalcin     PetscScalar *pointCoords;
1982066ea43fSLisandro Dalcin 
19836858538eSMatthew G. Knepley     PetscCall(DMGetCoordinateSection(*dm, &cs));
19846858538eSMatthew G. Knepley     PetscCall(PetscSectionSetNumFields(cs, 1));
19856858538eSMatthew G. Knepley     PetscCall(PetscSectionSetFieldComponents(cs, 0, coordDim));
19866858538eSMatthew G. Knepley     PetscCall(PetscSectionSetChart(cs, numCells, numCells + numVerts));
19876858538eSMatthew G. Knepley     for (v = numCells; v < numCells + numVerts; ++v) {
19886858538eSMatthew G. Knepley       PetscCall(PetscSectionSetDof(cs, v, coordDim));
19896858538eSMatthew G. Knepley       PetscCall(PetscSectionSetFieldDof(cs, v, 0, coordDim));
1990f45c9589SStefano Zampini     }
19916858538eSMatthew G. Knepley     PetscCall(PetscSectionSetUp(cs));
19926858538eSMatthew G. Knepley 
19936858538eSMatthew G. Knepley     /* We need to localize coordinates on cells */
19940598e1a2SLisandro Dalcin     if (periodic) {
19959db5b827SMatthew G. Knepley       PetscInt newStart = PETSC_MAX_INT, newEnd = -1, pStart, pEnd;
19969db5b827SMatthew G. Knepley 
19976858538eSMatthew G. Knepley       PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)cdmCell), &csCell));
19986858538eSMatthew G. Knepley       PetscCall(PetscSectionSetNumFields(csCell, 1));
19996858538eSMatthew G. Knepley       PetscCall(PetscSectionSetFieldComponents(csCell, 0, coordDim));
20009db5b827SMatthew G. Knepley       for (PetscInt h = 0; h <= maxHeight; h++) {
20019db5b827SMatthew G. Knepley         PetscCall(DMPlexGetHeightStratum(cdmCell, h, &pStart, &pEnd));
20029db5b827SMatthew G. Knepley         newStart = PetscMin(newStart, pStart);
20039db5b827SMatthew G. Knepley         newEnd   = PetscMax(newEnd, pEnd);
20049db5b827SMatthew G. Knepley       }
20059db5b827SMatthew G. Knepley       PetscCall(PetscSectionSetChart(csCell, newStart, newEnd));
20069db5b827SMatthew G. Knepley       for (PetscInt h = 0; h <= maxHeight; h++) {
20079db5b827SMatthew G. Knepley         PetscCall(DMPlexGetHeightStratum(cdmCell, h, &pStart, &pEnd));
20089db5b827SMatthew G. Knepley         for (PetscInt p = pStart; p < pEnd; ++p) {
20099db5b827SMatthew G. Knepley           PetscInt *closure = NULL;
20109db5b827SMatthew G. Knepley           PetscInt  Ncl, Nv = 0;
20116858538eSMatthew G. Knepley 
20129db5b827SMatthew G. Knepley           if (PetscUnlikely(PetscBTLookup(periodicCells[h], p - pStart))) {
20139db5b827SMatthew G. Knepley             PetscCall(DMPlexGetTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure));
20149db5b827SMatthew G. Knepley             for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) {
20159db5b827SMatthew G. Knepley               if (closure[cl] >= vStart && closure[cl] < vEnd) ++Nv;
20169db5b827SMatthew G. Knepley             }
20179db5b827SMatthew G. Knepley             PetscCall(DMPlexRestoreTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure));
20189db5b827SMatthew G. Knepley             PetscCall(PetscSectionSetDof(csCell, p, Nv * coordDim));
20199db5b827SMatthew G. Knepley             PetscCall(PetscSectionSetFieldDof(csCell, p, 0, Nv * coordDim));
20209db5b827SMatthew G. Knepley           }
2021f45c9589SStefano Zampini         }
2022f45c9589SStefano Zampini       }
20236858538eSMatthew G. Knepley       PetscCall(PetscSectionSetUp(csCell));
20246858538eSMatthew G. Knepley       PetscCall(DMSetCellCoordinateSection(*dm, PETSC_DETERMINE, csCell));
2025f45c9589SStefano Zampini     }
2026066ea43fSLisandro Dalcin 
20279566063dSJacob Faibussowitsch     PetscCall(DMCreateLocalVector(cdm, &coordinates));
20289566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &pointCoords));
20296858538eSMatthew G. Knepley     PetscCall(PetscMalloc1(numVerts, &nodeMap));
20306858538eSMatthew G. Knepley     for (n = 0; n < numNodes; n++)
20316858538eSMatthew G. Knepley       if (mesh->vertexMap[n] >= 0) nodeMap[mesh->vertexMap[n]] = n;
20326858538eSMatthew G. Knepley     for (v = 0; v < numVerts; ++v) {
20336858538eSMatthew G. Knepley       PetscInt off, node = nodeMap[v];
20346858538eSMatthew G. Knepley 
20356858538eSMatthew G. Knepley       PetscCall(PetscSectionGetOffset(cs, numCells + v, &off));
20366858538eSMatthew G. Knepley       for (d = 0; d < coordDim; ++d) pointCoords[off + d] = (PetscReal)coords[node * 3 + d];
20376858538eSMatthew G. Knepley     }
20386858538eSMatthew G. Knepley     PetscCall(VecRestoreArray(coordinates, &pointCoords));
20396858538eSMatthew G. Knepley 
20400598e1a2SLisandro Dalcin     if (periodic) {
20419db5b827SMatthew G. Knepley       PetscInt cStart, cEnd;
20429db5b827SMatthew G. Knepley 
20439db5b827SMatthew G. Knepley       PetscCall(DMPlexGetHeightStratum(cdmCell, 0, &cStart, &cEnd));
20446858538eSMatthew G. Knepley       PetscCall(DMCreateLocalVector(cdmCell, &coordinatesCell));
20456858538eSMatthew G. Knepley       PetscCall(VecGetArray(coordinatesCell, &pointCoords));
20469db5b827SMatthew G. Knepley       for (PetscInt c = cStart; c < cEnd; ++c) {
20479db5b827SMatthew G. Knepley         GmshElement *elem    = mesh->elements + c - cStart;
20489db5b827SMatthew G. Knepley         PetscInt    *closure = NULL;
20499db5b827SMatthew G. Knepley         PetscInt     verts[8];
20509db5b827SMatthew G. Knepley         PetscInt     Ncl, Nv = 0;
20519db5b827SMatthew G. Knepley 
20529db5b827SMatthew G. Knepley         for (PetscInt v = 0; v < elem->numVerts; ++v) cone[v] = elem->nodes[v];
20539db5b827SMatthew G. Knepley         PetscCall(DMPlexReorderCell(cdmCell, c, cone));
20549db5b827SMatthew G. Knepley         PetscCall(DMPlexGetTransitiveClosure(cdmCell, c, PETSC_TRUE, &Ncl, &closure));
20559db5b827SMatthew G. Knepley         for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) {
20569db5b827SMatthew G. Knepley           if (closure[cl] >= vStart && closure[cl] < vEnd) verts[Nv++] = closure[cl];
2057331830f3SMatthew G. Knepley         }
20589db5b827SMatthew 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);
20599db5b827SMatthew G. Knepley         for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) {
20609db5b827SMatthew G. Knepley           const PetscInt point = closure[cl];
20619db5b827SMatthew G. Knepley           PetscInt       hStart, h;
20629db5b827SMatthew G. Knepley 
20639db5b827SMatthew G. Knepley           PetscCall(DMPlexGetPointHeight(cdmCell, point, &h));
20649db5b827SMatthew G. Knepley           if (h > maxHeight) continue;
20659db5b827SMatthew G. Knepley           PetscCall(DMPlexGetHeightStratum(cdmCell, h, &hStart, NULL));
20669db5b827SMatthew G. Knepley           if (PetscUnlikely(PetscBTLookup(periodicCells[h], point - hStart))) {
20679db5b827SMatthew G. Knepley             PetscInt *pclosure = NULL;
20689db5b827SMatthew G. Knepley             PetscInt  Npcl, off, v;
20699db5b827SMatthew G. Knepley 
20709db5b827SMatthew G. Knepley             PetscCall(PetscSectionGetOffset(csCell, point, &off));
20719db5b827SMatthew G. Knepley             PetscCall(DMPlexGetTransitiveClosure(cdmCell, point, PETSC_TRUE, &Npcl, &pclosure));
20729db5b827SMatthew G. Knepley             for (PetscInt pcl = 0; pcl < Npcl * 2; pcl += 2) {
20739db5b827SMatthew G. Knepley               if (pclosure[pcl] >= vStart && pclosure[pcl] < vEnd) {
20749db5b827SMatthew G. Knepley                 for (v = 0; v < Nv; ++v)
20759db5b827SMatthew G. Knepley                   if (verts[v] == pclosure[pcl]) break;
20769db5b827SMatthew 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);
20779db5b827SMatthew G. Knepley                 for (PetscInt d = 0; d < coordDim; ++d) pointCoords[off++] = (PetscReal)coords[cone[v] * 3 + d];
20789db5b827SMatthew G. Knepley                 ++v;
20799db5b827SMatthew G. Knepley               }
20809db5b827SMatthew G. Knepley             }
20819db5b827SMatthew G. Knepley             PetscCall(DMPlexRestoreTransitiveClosure(cdmCell, point, PETSC_TRUE, &Npcl, &pclosure));
20829db5b827SMatthew G. Knepley           }
20839db5b827SMatthew G. Knepley         }
20849db5b827SMatthew G. Knepley         PetscCall(DMPlexRestoreTransitiveClosure(cdmCell, c, PETSC_TRUE, &Ncl, &closure));
2085331830f3SMatthew G. Knepley       }
20866858538eSMatthew G. Knepley       PetscCall(VecSetBlockSize(coordinatesCell, coordDim));
20876858538eSMatthew G. Knepley       PetscCall(VecRestoreArray(coordinatesCell, &pointCoords));
20886858538eSMatthew G. Knepley       PetscCall(DMSetCellCoordinatesLocal(*dm, coordinatesCell));
20896858538eSMatthew G. Knepley       PetscCall(VecDestroy(&coordinatesCell));
2090331830f3SMatthew G. Knepley     }
20919db5b827SMatthew G. Knepley     PetscCall(PetscFree(nodeMap));
20926858538eSMatthew G. Knepley     PetscCall(PetscSectionDestroy(&csCell));
20936858538eSMatthew G. Knepley     PetscCall(DMDestroy(&cdmCell));
2094066ea43fSLisandro Dalcin   }
2095066ea43fSLisandro Dalcin 
20969566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
20979566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, coordDim));
20989566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(*dm, coordinates));
20999566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
210011c56cb0SLisandro Dalcin 
21019566063dSJacob Faibussowitsch   PetscCall(GmshMeshDestroy(&mesh));
21029566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&periodicVerts));
2103eae3dc7dSJacob Faibussowitsch   if (periodic) {
2104eae3dc7dSJacob Faibussowitsch     for (PetscInt h = 0; h <= maxHeight; ++h) PetscCall(PetscBTDestroy(periodicCells + h));
2105eae3dc7dSJacob Faibussowitsch     PetscCall(PetscFree(periodicCells));
2106eae3dc7dSJacob Faibussowitsch   }
210711c56cb0SLisandro Dalcin 
2108066ea43fSLisandro Dalcin   if (highOrder && project) {
2109066ea43fSLisandro Dalcin     PetscFE         fe;
2110066ea43fSLisandro Dalcin     const char      prefix[]   = "dm_plex_gmsh_project_";
2111066ea43fSLisandro Dalcin     PetscBool       continuity = periodic ? PETSC_FALSE : PETSC_TRUE;
2112066ea43fSLisandro Dalcin     PetscDTNodeType nodeType   = PETSCDTNODES_GAUSSJACOBI;
2113066ea43fSLisandro Dalcin 
2114066ea43fSLisandro Dalcin     if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */
21159566063dSJacob Faibussowitsch     PetscCall(GmshCreateFE(comm, prefix, isSimplex, continuity, nodeType, dim, coordDim, order, &fe));
21169566063dSJacob Faibussowitsch     PetscCall(PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_project_fe_view"));
2117e44f6aebSMatthew G. Knepley     PetscCall(DMSetCoordinateDisc(*dm, fe, PETSC_TRUE));
21189566063dSJacob Faibussowitsch     PetscCall(PetscFEDestroy(&fe));
2119066ea43fSLisandro Dalcin   }
2120066ea43fSLisandro Dalcin 
21219566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CreateGmsh, *dm, NULL, NULL, NULL));
21223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2123331830f3SMatthew G. Knepley }
2124