xref: /petsc/src/dm/impls/plex/plexgmsh.c (revision 81a1af936b9b31e2ff66688fcd35d27758a44410)
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)                                   \
8066ea43fSLisandro Dalcin static int *GmshLexOrder_##T##_##p(void)                           \
9066ea43fSLisandro Dalcin {                                                                  \
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 
16b9bf55e5SMatthew G. Knepley static int *GmshLexOrder_QUA_2_Serendipity(void)
17b9bf55e5SMatthew G. Knepley {
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 */
22b9bf55e5SMatthew G. Knepley     lex[0] = 0; lex[2] = 1; lex[8] = 2; lex[6] = 3;
23b9bf55e5SMatthew G. Knepley     /* Edges */
24b9bf55e5SMatthew G. Knepley     lex[1] = 4; lex[5] = 5; lex[7] = 6; lex[3] = 7;
25b9bf55e5SMatthew G. Knepley     /* Cell */
26b9bf55e5SMatthew G. Knepley     lex[4] = -8;
27b9bf55e5SMatthew G. Knepley   }
28b9bf55e5SMatthew G. Knepley   return lex;
29b9bf55e5SMatthew G. Knepley }
30b9bf55e5SMatthew G. Knepley 
31b9bf55e5SMatthew G. Knepley static int *GmshLexOrder_HEX_2_Serendipity(void)
32b9bf55e5SMatthew G. Knepley {
33b9bf55e5SMatthew G. Knepley   static int Gmsh_LexOrder_HEX_2_Serendipity[27] = {-1};
34b9bf55e5SMatthew G. Knepley   int *lex = Gmsh_LexOrder_HEX_2_Serendipity;
35b9bf55e5SMatthew G. Knepley   if (lex[0] == -1) {
36b9bf55e5SMatthew G. Knepley     /* Vertices */
37b9bf55e5SMatthew G. Knepley     lex[ 0] =   0; lex[ 2] =   1; lex[ 8] =   2; lex[ 6] =   3;
38b9bf55e5SMatthew G. Knepley     lex[18] =   4; lex[20] =   5; lex[26] =   6; lex[24] =   7;
39b9bf55e5SMatthew G. Knepley     /* Edges */
40b9bf55e5SMatthew G. Knepley     lex[ 1] =   8; lex[ 3] =   9; lex[ 9] =  10; lex[ 5] =  11;
41b9bf55e5SMatthew G. Knepley     lex[11] =  12; lex[ 7] =  13; lex[17] =  14; lex[15] =  15;
42b9bf55e5SMatthew G. Knepley     lex[19] =  16; lex[21] =  17; lex[23] =  18; lex[25] =  19;
43b9bf55e5SMatthew G. Knepley     /* Faces */
44b9bf55e5SMatthew G. Knepley     lex[ 4] = -20; lex[10] = -21; lex[12] = -22; lex[14] = -23;
45b9bf55e5SMatthew G. Knepley     lex[16] = -24; lex[22] = -25;
46b9bf55e5SMatthew G. Knepley     /* Cell */
47b9bf55e5SMatthew G. Knepley     lex[13] = -26;
48b9bf55e5SMatthew G. Knepley   }
49b9bf55e5SMatthew G. Knepley   return lex;
50b9bf55e5SMatthew G. Knepley }
51b9bf55e5SMatthew G. Knepley 
52066ea43fSLisandro Dalcin #define GMSH_LEXORDER_LIST(T) \
53066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T,  1)     \
54066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T,  2)     \
55066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T,  3)     \
56066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T,  4)     \
57066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T,  5)     \
58066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T,  6)     \
59066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T,  7)     \
60066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T,  8)     \
61066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T,  9)     \
62066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 10)
63066ea43fSLisandro Dalcin 
64066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(VTX, 0)
65066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(SEG)
66066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(TRI)
67066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(QUA)
68066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(TET)
69066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(HEX)
70066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(PRI)
71066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(PYR)
72066ea43fSLisandro Dalcin 
73066ea43fSLisandro Dalcin typedef enum {
74066ea43fSLisandro Dalcin   GMSH_VTX = 0,
75066ea43fSLisandro Dalcin   GMSH_SEG = 1,
76066ea43fSLisandro Dalcin   GMSH_TRI = 2,
77066ea43fSLisandro Dalcin   GMSH_QUA = 3,
78066ea43fSLisandro Dalcin   GMSH_TET = 4,
79066ea43fSLisandro Dalcin   GMSH_HEX = 5,
80066ea43fSLisandro Dalcin   GMSH_PRI = 6,
81066ea43fSLisandro Dalcin   GMSH_PYR = 7,
82066ea43fSLisandro Dalcin   GMSH_NUM_POLYTOPES = 8
83066ea43fSLisandro Dalcin } GmshPolytopeType;
84066ea43fSLisandro Dalcin 
85de78e4feSLisandro Dalcin typedef struct {
860598e1a2SLisandro Dalcin   int   cellType;
87066ea43fSLisandro Dalcin   int   polytope;
880598e1a2SLisandro Dalcin   int   dim;
890598e1a2SLisandro Dalcin   int   order;
90066ea43fSLisandro Dalcin   int   numVerts;
910598e1a2SLisandro Dalcin   int   numNodes;
92066ea43fSLisandro Dalcin   int* (*lexorder)(void);
930598e1a2SLisandro Dalcin } GmshCellInfo;
940598e1a2SLisandro Dalcin 
95066ea43fSLisandro Dalcin #define GmshCellEntry(cellType, polytope, dim, order) \
96066ea43fSLisandro Dalcin   {cellType, GMSH_##polytope, dim, order, \
97066ea43fSLisandro Dalcin    GmshNumNodes_##polytope(1), \
98066ea43fSLisandro Dalcin    GmshNumNodes_##polytope(order), \
99066ea43fSLisandro Dalcin    GmshLexOrder_##polytope##_##order}
1000598e1a2SLisandro Dalcin 
1010598e1a2SLisandro Dalcin static const GmshCellInfo GmshCellTable[] = {
102066ea43fSLisandro Dalcin   GmshCellEntry( 15, VTX, 0,  0),
1030598e1a2SLisandro Dalcin 
104066ea43fSLisandro Dalcin   GmshCellEntry(  1, SEG, 1,  1),
105066ea43fSLisandro Dalcin   GmshCellEntry(  8, SEG, 1,  2),
106066ea43fSLisandro Dalcin   GmshCellEntry( 26, SEG, 1,  3),
107066ea43fSLisandro Dalcin   GmshCellEntry( 27, SEG, 1,  4),
108066ea43fSLisandro Dalcin   GmshCellEntry( 28, SEG, 1,  5),
109066ea43fSLisandro Dalcin   GmshCellEntry( 62, SEG, 1,  6),
110066ea43fSLisandro Dalcin   GmshCellEntry( 63, SEG, 1,  7),
111066ea43fSLisandro Dalcin   GmshCellEntry( 64, SEG, 1,  8),
112066ea43fSLisandro Dalcin   GmshCellEntry( 65, SEG, 1,  9),
113066ea43fSLisandro Dalcin   GmshCellEntry( 66, SEG, 1, 10),
1140598e1a2SLisandro Dalcin 
115066ea43fSLisandro Dalcin   GmshCellEntry(  2, TRI, 2,  1),
116066ea43fSLisandro Dalcin   GmshCellEntry(  9, TRI, 2,  2),
117066ea43fSLisandro Dalcin   GmshCellEntry( 21, TRI, 2,  3),
118066ea43fSLisandro Dalcin   GmshCellEntry( 23, TRI, 2,  4),
119066ea43fSLisandro Dalcin   GmshCellEntry( 25, TRI, 2,  5),
120066ea43fSLisandro Dalcin   GmshCellEntry( 42, TRI, 2,  6),
121066ea43fSLisandro Dalcin   GmshCellEntry( 43, TRI, 2,  7),
122066ea43fSLisandro Dalcin   GmshCellEntry( 44, TRI, 2,  8),
123066ea43fSLisandro Dalcin   GmshCellEntry( 45, TRI, 2,  9),
124066ea43fSLisandro Dalcin   GmshCellEntry( 46, TRI, 2, 10),
1250598e1a2SLisandro Dalcin 
126066ea43fSLisandro Dalcin   GmshCellEntry(  3, QUA, 2,  1),
127066ea43fSLisandro Dalcin   GmshCellEntry( 10, QUA, 2,  2),
128b9bf55e5SMatthew G. Knepley   {16, GMSH_QUA, 2, 2, 4, 8, GmshLexOrder_QUA_2_Serendipity},
129066ea43fSLisandro Dalcin   GmshCellEntry( 36, QUA, 2,  3),
130066ea43fSLisandro Dalcin   GmshCellEntry( 37, QUA, 2,  4),
131066ea43fSLisandro Dalcin   GmshCellEntry( 38, QUA, 2,  5),
132066ea43fSLisandro Dalcin   GmshCellEntry( 47, QUA, 2,  6),
133066ea43fSLisandro Dalcin   GmshCellEntry( 48, QUA, 2,  7),
134066ea43fSLisandro Dalcin   GmshCellEntry( 49, QUA, 2,  8),
135066ea43fSLisandro Dalcin   GmshCellEntry( 50, QUA, 2,  9),
136066ea43fSLisandro Dalcin   GmshCellEntry( 51, QUA, 2, 10),
1370598e1a2SLisandro Dalcin 
138066ea43fSLisandro Dalcin   GmshCellEntry(  4, TET, 3,  1),
139066ea43fSLisandro Dalcin   GmshCellEntry( 11, TET, 3,  2),
140066ea43fSLisandro Dalcin   GmshCellEntry( 29, TET, 3,  3),
141066ea43fSLisandro Dalcin   GmshCellEntry( 30, TET, 3,  4),
142066ea43fSLisandro Dalcin   GmshCellEntry( 31, TET, 3,  5),
143066ea43fSLisandro Dalcin   GmshCellEntry( 71, TET, 3,  6),
144066ea43fSLisandro Dalcin   GmshCellEntry( 72, TET, 3,  7),
145066ea43fSLisandro Dalcin   GmshCellEntry( 73, TET, 3,  8),
146066ea43fSLisandro Dalcin   GmshCellEntry( 74, TET, 3,  9),
147066ea43fSLisandro Dalcin   GmshCellEntry( 75, TET, 3, 10),
1480598e1a2SLisandro Dalcin 
149066ea43fSLisandro Dalcin   GmshCellEntry(  5, HEX, 3,  1),
150066ea43fSLisandro Dalcin   GmshCellEntry( 12, HEX, 3,  2),
151b9bf55e5SMatthew G. Knepley   {17, GMSH_HEX, 3, 2, 8, 20, GmshLexOrder_HEX_2_Serendipity},
152066ea43fSLisandro Dalcin   GmshCellEntry( 92, HEX, 3,  3),
153066ea43fSLisandro Dalcin   GmshCellEntry( 93, HEX, 3,  4),
154066ea43fSLisandro Dalcin   GmshCellEntry( 94, HEX, 3,  5),
155066ea43fSLisandro Dalcin   GmshCellEntry( 95, HEX, 3,  6),
156066ea43fSLisandro Dalcin   GmshCellEntry( 96, HEX, 3,  7),
157066ea43fSLisandro Dalcin   GmshCellEntry( 97, HEX, 3,  8),
158066ea43fSLisandro Dalcin   GmshCellEntry( 98, HEX, 3,  9),
159066ea43fSLisandro Dalcin   GmshCellEntry( -1, HEX, 3, 10),
1600598e1a2SLisandro Dalcin 
161066ea43fSLisandro Dalcin   GmshCellEntry(  6, PRI, 3,  1),
162066ea43fSLisandro Dalcin   GmshCellEntry( 13, PRI, 3,  2),
163066ea43fSLisandro Dalcin   GmshCellEntry( 90, PRI, 3,  3),
164066ea43fSLisandro Dalcin   GmshCellEntry( 91, PRI, 3,  4),
165066ea43fSLisandro Dalcin   GmshCellEntry(106, PRI, 3,  5),
166066ea43fSLisandro Dalcin   GmshCellEntry(107, PRI, 3,  6),
167066ea43fSLisandro Dalcin   GmshCellEntry(108, PRI, 3,  7),
168066ea43fSLisandro Dalcin   GmshCellEntry(109, PRI, 3,  8),
169066ea43fSLisandro Dalcin   GmshCellEntry(110, PRI, 3,  9),
170066ea43fSLisandro Dalcin   GmshCellEntry( -1, PRI, 3, 10),
1710598e1a2SLisandro Dalcin 
172066ea43fSLisandro Dalcin   GmshCellEntry(  7, PYR, 3,  1),
173066ea43fSLisandro Dalcin   GmshCellEntry( 14, PYR, 3,  2),
174066ea43fSLisandro Dalcin   GmshCellEntry(118, PYR, 3,  3),
175066ea43fSLisandro Dalcin   GmshCellEntry(119, PYR, 3,  4),
176066ea43fSLisandro Dalcin   GmshCellEntry(120, PYR, 3,  5),
177066ea43fSLisandro Dalcin   GmshCellEntry(121, PYR, 3,  6),
178066ea43fSLisandro Dalcin   GmshCellEntry(122, PYR, 3,  7),
179066ea43fSLisandro Dalcin   GmshCellEntry(123, PYR, 3,  8),
180066ea43fSLisandro Dalcin   GmshCellEntry(124, PYR, 3,  9),
181066ea43fSLisandro Dalcin   GmshCellEntry( -1, PYR, 3, 10)
1820598e1a2SLisandro Dalcin 
1830598e1a2SLisandro Dalcin #if 0
184066ea43fSLisandro Dalcin   {20, GMSH_TRI, 2, 3, 3,  9, NULL},
185066ea43fSLisandro Dalcin   {18, GMSH_PRI, 3, 2, 6, 15, NULL},
186066ea43fSLisandro Dalcin   {19, GMSH_PYR, 3, 2, 5, 13, NULL},
1870598e1a2SLisandro Dalcin #endif
1880598e1a2SLisandro Dalcin };
1890598e1a2SLisandro Dalcin 
1900598e1a2SLisandro Dalcin static GmshCellInfo GmshCellMap[150];
1910598e1a2SLisandro Dalcin 
1920598e1a2SLisandro Dalcin static PetscErrorCode GmshCellInfoSetUp(void)
1930598e1a2SLisandro Dalcin {
1940598e1a2SLisandro Dalcin   size_t           i, n;
1950598e1a2SLisandro Dalcin   static PetscBool called = PETSC_FALSE;
1960598e1a2SLisandro Dalcin 
1970598e1a2SLisandro Dalcin   if (called) return 0;
1980598e1a2SLisandro Dalcin   PetscFunctionBegin;
1990598e1a2SLisandro Dalcin   called = PETSC_TRUE;
2000598e1a2SLisandro Dalcin   n = sizeof(GmshCellMap)/sizeof(GmshCellMap[0]);
2010598e1a2SLisandro Dalcin   for (i = 0; i < n; ++i) {
2020598e1a2SLisandro Dalcin     GmshCellMap[i].cellType = -1;
203066ea43fSLisandro Dalcin     GmshCellMap[i].polytope = -1;
2040598e1a2SLisandro Dalcin   }
2050598e1a2SLisandro Dalcin   n = sizeof(GmshCellTable)/sizeof(GmshCellTable[0]);
206066ea43fSLisandro Dalcin   for (i = 0; i < n; ++i) {
207066ea43fSLisandro Dalcin     if (GmshCellTable[i].cellType <= 0) continue;
208066ea43fSLisandro Dalcin     GmshCellMap[GmshCellTable[i].cellType] = GmshCellTable[i];
209066ea43fSLisandro Dalcin   }
2100598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
2110598e1a2SLisandro Dalcin }
2120598e1a2SLisandro Dalcin 
2130598e1a2SLisandro Dalcin #define GmshCellTypeCheck(ct) 0; do { \
2140598e1a2SLisandro Dalcin     const int _ct_ = (int)ct; \
2150598e1a2SLisandro Dalcin     if (_ct_ < 0 || _ct_ >= (int)(sizeof(GmshCellMap)/sizeof(GmshCellMap[0]))) \
21698921bdaSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid Gmsh element type %d", _ct_); \
2170598e1a2SLisandro Dalcin     if (GmshCellMap[_ct_].cellType != _ct_) \
21898921bdaSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported Gmsh element type %d", _ct_); \
219066ea43fSLisandro Dalcin     if (GmshCellMap[_ct_].polytope == -1) \
22098921bdaSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported Gmsh element type %d", _ct_); \
2210598e1a2SLisandro Dalcin   } while (0)
2220598e1a2SLisandro Dalcin 
2230598e1a2SLisandro Dalcin typedef struct {
224698a79b9SLisandro Dalcin   PetscViewer  viewer;
225698a79b9SLisandro Dalcin   int          fileFormat;
226698a79b9SLisandro Dalcin   int          dataSize;
227698a79b9SLisandro Dalcin   PetscBool    binary;
228698a79b9SLisandro Dalcin   PetscBool    byteSwap;
229698a79b9SLisandro Dalcin   size_t       wlen;
230698a79b9SLisandro Dalcin   void        *wbuf;
231698a79b9SLisandro Dalcin   size_t       slen;
232698a79b9SLisandro Dalcin   void        *sbuf;
2330598e1a2SLisandro Dalcin   PetscInt    *nbuf;
2340598e1a2SLisandro Dalcin   PetscInt     nodeStart;
2350598e1a2SLisandro Dalcin   PetscInt     nodeEnd;
23633a088b6SMatthew G. Knepley   PetscInt    *nodeMap;
237698a79b9SLisandro Dalcin } GmshFile;
238de78e4feSLisandro Dalcin 
239698a79b9SLisandro Dalcin static PetscErrorCode GmshBufferGet(GmshFile *gmsh, size_t count, size_t eltsize, void *buf)
240de78e4feSLisandro Dalcin {
241de78e4feSLisandro Dalcin   size_t         size = count * eltsize;
24211c56cb0SLisandro Dalcin   PetscErrorCode ierr;
24311c56cb0SLisandro Dalcin 
24411c56cb0SLisandro Dalcin   PetscFunctionBegin;
245698a79b9SLisandro Dalcin   if (gmsh->wlen < size) {
246698a79b9SLisandro Dalcin     ierr = PetscFree(gmsh->wbuf);CHKERRQ(ierr);
247698a79b9SLisandro Dalcin     ierr = PetscMalloc(size, &gmsh->wbuf);CHKERRQ(ierr);
248698a79b9SLisandro Dalcin     gmsh->wlen = size;
249de78e4feSLisandro Dalcin   }
250698a79b9SLisandro Dalcin   *(void**)buf = size ? gmsh->wbuf : NULL;
251de78e4feSLisandro Dalcin   PetscFunctionReturn(0);
252de78e4feSLisandro Dalcin }
253de78e4feSLisandro Dalcin 
254698a79b9SLisandro Dalcin static PetscErrorCode GmshBufferSizeGet(GmshFile *gmsh, size_t count, void *buf)
255698a79b9SLisandro Dalcin {
256698a79b9SLisandro Dalcin   size_t         dataSize = (size_t)gmsh->dataSize;
257698a79b9SLisandro Dalcin   size_t         size = count * dataSize;
258698a79b9SLisandro Dalcin   PetscErrorCode ierr;
259698a79b9SLisandro Dalcin 
260698a79b9SLisandro Dalcin   PetscFunctionBegin;
261698a79b9SLisandro Dalcin   if (gmsh->slen < size) {
262698a79b9SLisandro Dalcin     ierr = PetscFree(gmsh->sbuf);CHKERRQ(ierr);
263698a79b9SLisandro Dalcin     ierr = PetscMalloc(size, &gmsh->sbuf);CHKERRQ(ierr);
264698a79b9SLisandro Dalcin     gmsh->slen = size;
265698a79b9SLisandro Dalcin   }
266698a79b9SLisandro Dalcin   *(void**)buf = size ? gmsh->sbuf : NULL;
267698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
268698a79b9SLisandro Dalcin }
269698a79b9SLisandro Dalcin 
270698a79b9SLisandro Dalcin static PetscErrorCode GmshRead(GmshFile *gmsh, void *buf, PetscInt count, PetscDataType dtype)
271de78e4feSLisandro Dalcin {
272de78e4feSLisandro Dalcin   PetscErrorCode ierr;
273de78e4feSLisandro Dalcin   PetscFunctionBegin;
274698a79b9SLisandro Dalcin   ierr = PetscViewerRead(gmsh->viewer, buf, count, NULL, dtype);CHKERRQ(ierr);
275698a79b9SLisandro Dalcin   if (gmsh->byteSwap) {ierr = PetscByteSwap(buf, dtype, count);CHKERRQ(ierr);}
276698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
277698a79b9SLisandro Dalcin }
278698a79b9SLisandro Dalcin 
279698a79b9SLisandro Dalcin static PetscErrorCode GmshReadString(GmshFile *gmsh, char *buf, PetscInt count)
280698a79b9SLisandro Dalcin {
281698a79b9SLisandro Dalcin   PetscErrorCode ierr;
282698a79b9SLisandro Dalcin   PetscFunctionBegin;
283698a79b9SLisandro Dalcin   ierr = PetscViewerRead(gmsh->viewer, buf, count, NULL, PETSC_STRING);CHKERRQ(ierr);
284698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
285698a79b9SLisandro Dalcin }
286698a79b9SLisandro Dalcin 
287d6689ca9SLisandro Dalcin static PetscErrorCode GmshMatch(PETSC_UNUSED GmshFile *gmsh, const char Section[], char line[PETSC_MAX_PATH_LEN], PetscBool *match)
288d6689ca9SLisandro Dalcin {
289d6689ca9SLisandro Dalcin   PetscErrorCode ierr;
290d6689ca9SLisandro Dalcin   PetscFunctionBegin;
291d6689ca9SLisandro Dalcin   ierr = PetscStrcmp(line, Section, match);CHKERRQ(ierr);
292d6689ca9SLisandro Dalcin   PetscFunctionReturn(0);
293d6689ca9SLisandro Dalcin }
294d6689ca9SLisandro Dalcin 
295d6689ca9SLisandro Dalcin static PetscErrorCode GmshExpect(GmshFile *gmsh, const char Section[], char line[PETSC_MAX_PATH_LEN])
296d6689ca9SLisandro Dalcin {
297d6689ca9SLisandro Dalcin   PetscBool      match;
298d6689ca9SLisandro Dalcin   PetscErrorCode ierr;
299d6689ca9SLisandro Dalcin 
300d6689ca9SLisandro Dalcin   PetscFunctionBegin;
301d6689ca9SLisandro Dalcin   ierr = GmshMatch(gmsh, Section, line, &match);CHKERRQ(ierr);
3022c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!match,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file, expecting %s",Section);
303d6689ca9SLisandro Dalcin   PetscFunctionReturn(0);
304d6689ca9SLisandro Dalcin }
305d6689ca9SLisandro Dalcin 
306d6689ca9SLisandro Dalcin static PetscErrorCode GmshReadSection(GmshFile *gmsh, char line[PETSC_MAX_PATH_LEN])
307d6689ca9SLisandro Dalcin {
308d6689ca9SLisandro Dalcin   PetscBool      match;
309d6689ca9SLisandro Dalcin   PetscErrorCode ierr;
310d6689ca9SLisandro Dalcin 
311d6689ca9SLisandro Dalcin   PetscFunctionBegin;
312d6689ca9SLisandro Dalcin   while (PETSC_TRUE) {
313d6689ca9SLisandro Dalcin     ierr = GmshReadString(gmsh, line, 1);CHKERRQ(ierr);
314d6689ca9SLisandro Dalcin     ierr = GmshMatch(gmsh, "$Comments", line, &match);CHKERRQ(ierr);
315d6689ca9SLisandro Dalcin     if (!match) break;
316d6689ca9SLisandro Dalcin     while (PETSC_TRUE) {
317d6689ca9SLisandro Dalcin       ierr = GmshReadString(gmsh, line, 1);CHKERRQ(ierr);
318d6689ca9SLisandro Dalcin       ierr = GmshMatch(gmsh, "$EndComments", line, &match);CHKERRQ(ierr);
319d6689ca9SLisandro Dalcin       if (match) break;
320d6689ca9SLisandro Dalcin     }
321d6689ca9SLisandro Dalcin   }
322d6689ca9SLisandro Dalcin   PetscFunctionReturn(0);
323d6689ca9SLisandro Dalcin }
324d6689ca9SLisandro Dalcin 
325d6689ca9SLisandro Dalcin static PetscErrorCode GmshReadEndSection(GmshFile *gmsh, const char EndSection[], char line[PETSC_MAX_PATH_LEN])
326d6689ca9SLisandro Dalcin {
327d6689ca9SLisandro Dalcin   PetscErrorCode ierr;
328d6689ca9SLisandro Dalcin   PetscFunctionBegin;
329d6689ca9SLisandro Dalcin   ierr = GmshReadString(gmsh, line, 1);CHKERRQ(ierr);
330d6689ca9SLisandro Dalcin   ierr = GmshExpect(gmsh, EndSection, line);CHKERRQ(ierr);
331d6689ca9SLisandro Dalcin   PetscFunctionReturn(0);
332d6689ca9SLisandro Dalcin }
333d6689ca9SLisandro Dalcin 
334698a79b9SLisandro Dalcin static PetscErrorCode GmshReadSize(GmshFile *gmsh, PetscInt *buf, PetscInt count)
335698a79b9SLisandro Dalcin {
336698a79b9SLisandro Dalcin   PetscInt       i;
337698a79b9SLisandro Dalcin   size_t         dataSize = (size_t)gmsh->dataSize;
338698a79b9SLisandro Dalcin   PetscErrorCode ierr;
339698a79b9SLisandro Dalcin 
340698a79b9SLisandro Dalcin   PetscFunctionBegin;
341698a79b9SLisandro Dalcin   if (dataSize == sizeof(PetscInt)) {
342698a79b9SLisandro Dalcin     ierr = GmshRead(gmsh, buf, count, PETSC_INT);CHKERRQ(ierr);
343698a79b9SLisandro Dalcin   } else  if (dataSize == sizeof(int)) {
344698a79b9SLisandro Dalcin     int *ibuf = NULL;
34589d5b078SSatish Balay     ierr = GmshBufferSizeGet(gmsh, count, &ibuf);CHKERRQ(ierr);
346698a79b9SLisandro Dalcin     ierr = GmshRead(gmsh, ibuf, count, PETSC_ENUM);CHKERRQ(ierr);
347698a79b9SLisandro Dalcin     for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i];
348698a79b9SLisandro Dalcin   } else  if (dataSize == sizeof(long)) {
349698a79b9SLisandro Dalcin     long *ibuf = NULL;
35089d5b078SSatish Balay     ierr = GmshBufferSizeGet(gmsh, count, &ibuf);CHKERRQ(ierr);
351698a79b9SLisandro Dalcin     ierr = GmshRead(gmsh, ibuf, count, PETSC_LONG);CHKERRQ(ierr);
352698a79b9SLisandro Dalcin     for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i];
353698a79b9SLisandro Dalcin   } else if (dataSize == sizeof(PetscInt64)) {
354698a79b9SLisandro Dalcin     PetscInt64 *ibuf = NULL;
35589d5b078SSatish Balay     ierr = GmshBufferSizeGet(gmsh, count, &ibuf);CHKERRQ(ierr);
356698a79b9SLisandro Dalcin     ierr = GmshRead(gmsh, ibuf, count, PETSC_INT64);CHKERRQ(ierr);
357698a79b9SLisandro Dalcin     for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i];
358698a79b9SLisandro Dalcin   }
359698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
360698a79b9SLisandro Dalcin }
361698a79b9SLisandro Dalcin 
362698a79b9SLisandro Dalcin static PetscErrorCode GmshReadInt(GmshFile *gmsh, int *buf, PetscInt count)
363698a79b9SLisandro Dalcin {
364698a79b9SLisandro Dalcin   PetscErrorCode ierr;
365698a79b9SLisandro Dalcin   PetscFunctionBegin;
366698a79b9SLisandro Dalcin   ierr = GmshRead(gmsh, buf, count, PETSC_ENUM);CHKERRQ(ierr);
367698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
368698a79b9SLisandro Dalcin }
369698a79b9SLisandro Dalcin 
370698a79b9SLisandro Dalcin static PetscErrorCode GmshReadDouble(GmshFile *gmsh, double *buf, PetscInt count)
371698a79b9SLisandro Dalcin {
372698a79b9SLisandro Dalcin   PetscErrorCode ierr;
373698a79b9SLisandro Dalcin   PetscFunctionBegin;
374698a79b9SLisandro Dalcin   ierr = GmshRead(gmsh, buf, count, PETSC_DOUBLE);CHKERRQ(ierr);
375de78e4feSLisandro Dalcin   PetscFunctionReturn(0);
376de78e4feSLisandro Dalcin }
377de78e4feSLisandro Dalcin 
378de78e4feSLisandro Dalcin typedef struct {
3790598e1a2SLisandro Dalcin   PetscInt id;       /* Entity ID */
3800598e1a2SLisandro Dalcin   PetscInt dim;      /* Dimension */
381de78e4feSLisandro Dalcin   double   bbox[6];  /* Bounding box */
382de78e4feSLisandro Dalcin   PetscInt numTags;  /* Size of tag array */
383de78e4feSLisandro Dalcin   int      tags[4];  /* Tag array */
384de78e4feSLisandro Dalcin } GmshEntity;
385de78e4feSLisandro Dalcin 
386de78e4feSLisandro Dalcin typedef struct {
387730356f6SLisandro Dalcin   GmshEntity *entity[4];
388730356f6SLisandro Dalcin   PetscHMapI  entityMap[4];
389730356f6SLisandro Dalcin } GmshEntities;
390730356f6SLisandro Dalcin 
391698a79b9SLisandro Dalcin static PetscErrorCode GmshEntitiesCreate(PetscInt count[4], GmshEntities **entities)
392730356f6SLisandro Dalcin {
393730356f6SLisandro Dalcin   PetscInt       dim;
394730356f6SLisandro Dalcin   PetscErrorCode ierr;
395730356f6SLisandro Dalcin 
396730356f6SLisandro Dalcin   PetscFunctionBegin;
397730356f6SLisandro Dalcin   ierr = PetscNew(entities);CHKERRQ(ierr);
398730356f6SLisandro Dalcin   for (dim = 0; dim < 4; ++dim) {
399730356f6SLisandro Dalcin     ierr = PetscCalloc1(count[dim], &(*entities)->entity[dim]);CHKERRQ(ierr);
400730356f6SLisandro Dalcin     ierr = PetscHMapICreate(&(*entities)->entityMap[dim]);CHKERRQ(ierr);
401730356f6SLisandro Dalcin   }
402730356f6SLisandro Dalcin   PetscFunctionReturn(0);
403730356f6SLisandro Dalcin }
404730356f6SLisandro Dalcin 
4050598e1a2SLisandro Dalcin static PetscErrorCode GmshEntitiesDestroy(GmshEntities **entities)
4060598e1a2SLisandro Dalcin {
4070598e1a2SLisandro Dalcin   PetscInt       dim;
4080598e1a2SLisandro Dalcin   PetscErrorCode ierr;
4090598e1a2SLisandro Dalcin 
4100598e1a2SLisandro Dalcin   PetscFunctionBegin;
4110598e1a2SLisandro Dalcin   if (!*entities) PetscFunctionReturn(0);
4120598e1a2SLisandro Dalcin   for (dim = 0; dim < 4; ++dim) {
4130598e1a2SLisandro Dalcin     ierr = PetscFree((*entities)->entity[dim]);CHKERRQ(ierr);
4140598e1a2SLisandro Dalcin     ierr = PetscHMapIDestroy(&(*entities)->entityMap[dim]);CHKERRQ(ierr);
4150598e1a2SLisandro Dalcin   }
4160598e1a2SLisandro Dalcin   ierr = PetscFree((*entities));CHKERRQ(ierr);
4170598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
4180598e1a2SLisandro Dalcin }
4190598e1a2SLisandro Dalcin 
420730356f6SLisandro Dalcin static PetscErrorCode GmshEntitiesAdd(GmshEntities *entities, PetscInt index, PetscInt dim, PetscInt eid, GmshEntity** entity)
421730356f6SLisandro Dalcin {
422730356f6SLisandro Dalcin   PetscErrorCode ierr;
4230598e1a2SLisandro Dalcin 
424730356f6SLisandro Dalcin   PetscFunctionBegin;
425730356f6SLisandro Dalcin   ierr = PetscHMapISet(entities->entityMap[dim], eid, index);CHKERRQ(ierr);
426730356f6SLisandro Dalcin   entities->entity[dim][index].dim = dim;
427730356f6SLisandro Dalcin   entities->entity[dim][index].id  = eid;
428730356f6SLisandro Dalcin   if (entity) *entity = &entities->entity[dim][index];
429730356f6SLisandro Dalcin   PetscFunctionReturn(0);
430730356f6SLisandro Dalcin }
431730356f6SLisandro Dalcin 
432730356f6SLisandro Dalcin static PetscErrorCode GmshEntitiesGet(GmshEntities *entities, PetscInt dim, PetscInt eid, GmshEntity** entity)
433730356f6SLisandro Dalcin {
434730356f6SLisandro Dalcin   PetscInt       index;
435730356f6SLisandro Dalcin   PetscErrorCode ierr;
436730356f6SLisandro Dalcin 
437730356f6SLisandro Dalcin   PetscFunctionBegin;
438730356f6SLisandro Dalcin   ierr = PetscHMapIGet(entities->entityMap[dim], eid, &index);CHKERRQ(ierr);
439730356f6SLisandro Dalcin   *entity = &entities->entity[dim][index];
440730356f6SLisandro Dalcin   PetscFunctionReturn(0);
441730356f6SLisandro Dalcin }
442730356f6SLisandro Dalcin 
4430598e1a2SLisandro Dalcin typedef struct {
4440598e1a2SLisandro Dalcin   PetscInt *id;  /* Node IDs */
4450598e1a2SLisandro Dalcin   double   *xyz; /* Coordinates */
446*81a1af93SMatthew G. Knepley   PetscInt *tag; /* Physical tag */
4470598e1a2SLisandro Dalcin } GmshNodes;
4480598e1a2SLisandro Dalcin 
4490598e1a2SLisandro Dalcin static PetscErrorCode GmshNodesCreate(PetscInt count, GmshNodes **nodes)
450730356f6SLisandro Dalcin {
451730356f6SLisandro Dalcin   PetscErrorCode ierr;
452730356f6SLisandro Dalcin 
453730356f6SLisandro Dalcin   PetscFunctionBegin;
4540598e1a2SLisandro Dalcin   ierr = PetscNew(nodes);CHKERRQ(ierr);
4550598e1a2SLisandro Dalcin   ierr = PetscMalloc1(count*1, &(*nodes)->id);CHKERRQ(ierr);
4560598e1a2SLisandro Dalcin   ierr = PetscMalloc1(count*3, &(*nodes)->xyz);CHKERRQ(ierr);
457*81a1af93SMatthew G. Knepley   ierr = PetscMalloc1(count*1, &(*nodes)->tag);CHKERRQ(ierr);
4580598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
459730356f6SLisandro Dalcin }
4600598e1a2SLisandro Dalcin 
4610598e1a2SLisandro Dalcin static PetscErrorCode GmshNodesDestroy(GmshNodes **nodes)
4620598e1a2SLisandro Dalcin {
4630598e1a2SLisandro Dalcin   PetscErrorCode ierr;
4640598e1a2SLisandro Dalcin   PetscFunctionBegin;
4650598e1a2SLisandro Dalcin   if (!*nodes) PetscFunctionReturn(0);
4660598e1a2SLisandro Dalcin   ierr = PetscFree((*nodes)->id);CHKERRQ(ierr);
4670598e1a2SLisandro Dalcin   ierr = PetscFree((*nodes)->xyz);CHKERRQ(ierr);
468*81a1af93SMatthew G. Knepley   ierr = PetscFree((*nodes)->tag);CHKERRQ(ierr);
4690598e1a2SLisandro Dalcin   ierr = PetscFree((*nodes));CHKERRQ(ierr);
470730356f6SLisandro Dalcin   PetscFunctionReturn(0);
471730356f6SLisandro Dalcin }
472730356f6SLisandro Dalcin 
473730356f6SLisandro Dalcin typedef struct {
4740598e1a2SLisandro Dalcin   PetscInt id;       /* Element ID */
4750598e1a2SLisandro Dalcin   PetscInt dim;      /* Dimension */
476de78e4feSLisandro Dalcin   PetscInt cellType; /* Cell type */
4770598e1a2SLisandro Dalcin   PetscInt numVerts; /* Size of vertex array */
478de78e4feSLisandro Dalcin   PetscInt numNodes; /* Size of node array */
4790598e1a2SLisandro Dalcin   PetscInt *nodes;   /* Vertex/Node array */
480*81a1af93SMatthew G. Knepley   PetscInt numTags;  /* Size of physical tag array */
481*81a1af93SMatthew G. Knepley   int      tags[4];  /* Physical tag array */
482de78e4feSLisandro Dalcin } GmshElement;
483de78e4feSLisandro Dalcin 
4840598e1a2SLisandro Dalcin static PetscErrorCode GmshElementsCreate(PetscInt count, GmshElement **elements)
4850598e1a2SLisandro Dalcin {
4860598e1a2SLisandro Dalcin   PetscErrorCode ierr;
4870598e1a2SLisandro Dalcin 
4880598e1a2SLisandro Dalcin   PetscFunctionBegin;
4890598e1a2SLisandro Dalcin   ierr = PetscCalloc1(count, elements);CHKERRQ(ierr);
4900598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
4910598e1a2SLisandro Dalcin }
4920598e1a2SLisandro Dalcin 
4930598e1a2SLisandro Dalcin static PetscErrorCode GmshElementsDestroy(GmshElement **elements)
4940598e1a2SLisandro Dalcin {
4950598e1a2SLisandro Dalcin   PetscErrorCode ierr;
4960598e1a2SLisandro Dalcin 
4970598e1a2SLisandro Dalcin   PetscFunctionBegin;
4980598e1a2SLisandro Dalcin   if (!*elements) PetscFunctionReturn(0);
4990598e1a2SLisandro Dalcin   ierr = PetscFree(*elements);CHKERRQ(ierr);
5000598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
5010598e1a2SLisandro Dalcin }
5020598e1a2SLisandro Dalcin 
5030598e1a2SLisandro Dalcin typedef struct {
5040598e1a2SLisandro Dalcin   PetscInt       dim;
505066ea43fSLisandro Dalcin   PetscInt       order;
5060598e1a2SLisandro Dalcin   GmshEntities  *entities;
5070598e1a2SLisandro Dalcin   PetscInt       numNodes;
5080598e1a2SLisandro Dalcin   GmshNodes     *nodelist;
5090598e1a2SLisandro Dalcin   PetscInt       numElems;
5100598e1a2SLisandro Dalcin   GmshElement   *elements;
5110598e1a2SLisandro Dalcin   PetscInt       numVerts;
5120598e1a2SLisandro Dalcin   PetscInt       numCells;
5130598e1a2SLisandro Dalcin   PetscInt      *periodMap;
5140598e1a2SLisandro Dalcin   PetscInt      *vertexMap;
5150598e1a2SLisandro Dalcin   PetscSegBuffer segbuf;
516a45dabc8SMatthew G. Knepley   PetscInt       numRegions;
517a45dabc8SMatthew G. Knepley   PetscInt      *regionTags;
518a45dabc8SMatthew G. Knepley   char         **regionNames;
5190598e1a2SLisandro Dalcin } GmshMesh;
5200598e1a2SLisandro Dalcin 
5210598e1a2SLisandro Dalcin static PetscErrorCode GmshMeshCreate(GmshMesh **mesh)
5220598e1a2SLisandro Dalcin {
5230598e1a2SLisandro Dalcin   PetscErrorCode ierr;
5240598e1a2SLisandro Dalcin 
5250598e1a2SLisandro Dalcin   PetscFunctionBegin;
5260598e1a2SLisandro Dalcin   ierr = PetscNew(mesh);CHKERRQ(ierr);
5270598e1a2SLisandro Dalcin   ierr = PetscSegBufferCreate(sizeof(PetscInt), 0, &(*mesh)->segbuf);CHKERRQ(ierr);
5280598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
5290598e1a2SLisandro Dalcin }
5300598e1a2SLisandro Dalcin 
5310598e1a2SLisandro Dalcin static PetscErrorCode GmshMeshDestroy(GmshMesh **mesh)
5320598e1a2SLisandro Dalcin {
533a45dabc8SMatthew G. Knepley   PetscInt       r;
5340598e1a2SLisandro Dalcin   PetscErrorCode ierr;
5350598e1a2SLisandro Dalcin 
5360598e1a2SLisandro Dalcin   PetscFunctionBegin;
5370598e1a2SLisandro Dalcin   if (!*mesh) PetscFunctionReturn(0);
5380598e1a2SLisandro Dalcin   ierr = GmshEntitiesDestroy(&(*mesh)->entities);CHKERRQ(ierr);
5390598e1a2SLisandro Dalcin   ierr = GmshNodesDestroy(&(*mesh)->nodelist);CHKERRQ(ierr);
5400598e1a2SLisandro Dalcin   ierr = GmshElementsDestroy(&(*mesh)->elements);CHKERRQ(ierr);
5410598e1a2SLisandro Dalcin   ierr = PetscFree((*mesh)->periodMap);CHKERRQ(ierr);
5420598e1a2SLisandro Dalcin   ierr = PetscFree((*mesh)->vertexMap);CHKERRQ(ierr);
5430598e1a2SLisandro Dalcin   ierr = PetscSegBufferDestroy(&(*mesh)->segbuf);CHKERRQ(ierr);
544a45dabc8SMatthew G. Knepley   for (r = 0; r < (*mesh)->numRegions; ++r) {ierr = PetscFree((*mesh)->regionNames[r]);CHKERRQ(ierr);}
545a45dabc8SMatthew G. Knepley   ierr = PetscFree2((*mesh)->regionTags, (*mesh)->regionNames);CHKERRQ(ierr);
5460598e1a2SLisandro Dalcin   ierr = PetscFree((*mesh));CHKERRQ(ierr);
5470598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
5480598e1a2SLisandro Dalcin }
5490598e1a2SLisandro Dalcin 
5500598e1a2SLisandro Dalcin static PetscErrorCode GmshReadNodes_v22(GmshFile *gmsh, GmshMesh *mesh)
551de78e4feSLisandro Dalcin {
552698a79b9SLisandro Dalcin   PetscViewer    viewer = gmsh->viewer;
553698a79b9SLisandro Dalcin   PetscBool      byteSwap = gmsh->byteSwap;
554de78e4feSLisandro Dalcin   char           line[PETSC_MAX_PATH_LEN];
5550598e1a2SLisandro Dalcin   int            n, num, nid, snum;
5560598e1a2SLisandro Dalcin   GmshNodes      *nodes;
557de78e4feSLisandro Dalcin   PetscErrorCode ierr;
558de78e4feSLisandro Dalcin 
559de78e4feSLisandro Dalcin   PetscFunctionBegin;
560de78e4feSLisandro Dalcin   ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr);
561698a79b9SLisandro Dalcin   snum = sscanf(line, "%d", &num);
5622c71b3e2SJacob Faibussowitsch   PetscCheckFalse(snum != 1,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
5630598e1a2SLisandro Dalcin   ierr = GmshNodesCreate(num, &nodes);CHKERRQ(ierr);
5640598e1a2SLisandro Dalcin   mesh->numNodes = num;
5650598e1a2SLisandro Dalcin   mesh->nodelist = nodes;
5660598e1a2SLisandro Dalcin   for (n = 0; n < num; ++n) {
5670598e1a2SLisandro Dalcin     double *xyz = nodes->xyz + n*3;
56811c56cb0SLisandro Dalcin     ierr = PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM);CHKERRQ(ierr);
56911c56cb0SLisandro Dalcin     ierr = PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE);CHKERRQ(ierr);
5700598e1a2SLisandro Dalcin     if (byteSwap) {ierr = PetscByteSwap(&nid, PETSC_ENUM, 1);CHKERRQ(ierr);}
57111c56cb0SLisandro Dalcin     if (byteSwap) {ierr = PetscByteSwap(xyz, PETSC_DOUBLE, 3);CHKERRQ(ierr);}
5720598e1a2SLisandro Dalcin     nodes->id[n] = nid;
573*81a1af93SMatthew G. Knepley     nodes->tag[n] = -1;
57411c56cb0SLisandro Dalcin   }
57511c56cb0SLisandro Dalcin   PetscFunctionReturn(0);
57611c56cb0SLisandro Dalcin }
57711c56cb0SLisandro Dalcin 
578de78e4feSLisandro Dalcin /* Gmsh elements can be of any dimension/co-dimension, so we need to traverse the
579de78e4feSLisandro Dalcin    file contents multiple times to figure out the true number of cells and facets
580de78e4feSLisandro Dalcin    in the given mesh. To make this more efficient we read the file contents only
581de78e4feSLisandro Dalcin    once and store them in memory, while determining the true number of cells. */
5820598e1a2SLisandro Dalcin static PetscErrorCode GmshReadElements_v22(GmshFile* gmsh, GmshMesh *mesh)
58311c56cb0SLisandro Dalcin {
584698a79b9SLisandro Dalcin   PetscViewer    viewer = gmsh->viewer;
585698a79b9SLisandro Dalcin   PetscBool      binary = gmsh->binary;
586698a79b9SLisandro Dalcin   PetscBool      byteSwap = gmsh->byteSwap;
587de78e4feSLisandro Dalcin   char           line[PETSC_MAX_PATH_LEN];
5880598e1a2SLisandro Dalcin   int            i, c, p, num, ibuf[1+4+1000], snum;
5890598e1a2SLisandro Dalcin   int            cellType, numElem, numVerts, numNodes, numTags;
590df032b82SMatthew G. Knepley   GmshElement   *elements;
5910598e1a2SLisandro Dalcin   PetscInt      *nodeMap = gmsh->nodeMap;
592df032b82SMatthew G. Knepley   PetscErrorCode ierr;
593df032b82SMatthew G. Knepley 
594df032b82SMatthew G. Knepley   PetscFunctionBegin;
595feb237baSPierre Jolivet   ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr);
596698a79b9SLisandro Dalcin   snum = sscanf(line, "%d", &num);
5972c71b3e2SJacob Faibussowitsch   PetscCheckFalse(snum != 1,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
5980598e1a2SLisandro Dalcin   ierr = GmshElementsCreate(num, &elements);CHKERRQ(ierr);
5990598e1a2SLisandro Dalcin   mesh->numElems = num;
6000598e1a2SLisandro Dalcin   mesh->elements = elements;
601698a79b9SLisandro Dalcin   for (c = 0; c < num;) {
60211c56cb0SLisandro Dalcin     ierr = PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM);CHKERRQ(ierr);
60311c56cb0SLisandro Dalcin     if (byteSwap) {ierr = PetscByteSwap(ibuf, PETSC_ENUM, 3);CHKERRQ(ierr);}
6040598e1a2SLisandro Dalcin 
6050598e1a2SLisandro Dalcin     cellType = binary ? ibuf[0] : ibuf[1];
6060598e1a2SLisandro Dalcin     numElem  = binary ? ibuf[1] : 1;
607df032b82SMatthew G. Knepley     numTags  = ibuf[2];
6080598e1a2SLisandro Dalcin 
6090598e1a2SLisandro Dalcin     ierr = GmshCellTypeCheck(cellType);CHKERRQ(ierr);
6100598e1a2SLisandro Dalcin     numVerts = GmshCellMap[cellType].numVerts;
6110598e1a2SLisandro Dalcin     numNodes = GmshCellMap[cellType].numNodes;
6120598e1a2SLisandro Dalcin 
613df032b82SMatthew G. Knepley     for (i = 0; i < numElem; ++i, ++c) {
6140598e1a2SLisandro Dalcin       GmshElement *element = elements + c;
6150598e1a2SLisandro Dalcin       const int off = binary ? 0 : 1, nint = 1 + numTags + numNodes - off;
6160598e1a2SLisandro Dalcin       const int *id = ibuf, *nodes = ibuf + 1 + numTags, *tags = ibuf + 1;
6170598e1a2SLisandro Dalcin       ierr = PetscViewerRead(viewer, ibuf+off, nint, NULL, PETSC_ENUM);CHKERRQ(ierr);
6180598e1a2SLisandro Dalcin       if (byteSwap) {ierr = PetscByteSwap(ibuf+off, PETSC_ENUM, nint);CHKERRQ(ierr);}
6190598e1a2SLisandro Dalcin       element->id  = id[0];
6200598e1a2SLisandro Dalcin       element->dim = GmshCellMap[cellType].dim;
6210598e1a2SLisandro Dalcin       element->cellType = cellType;
6220598e1a2SLisandro Dalcin       element->numVerts = numVerts;
6230598e1a2SLisandro Dalcin       element->numNodes = numNodes;
6240598e1a2SLisandro Dalcin       element->numTags  = PetscMin(numTags, 4);
6250598e1a2SLisandro Dalcin       ierr = PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes);CHKERRQ(ierr);
6260598e1a2SLisandro Dalcin       for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]];
6270598e1a2SLisandro Dalcin       for (p = 0; p < element->numTags;  p++) element->tags[p]  = tags[p];
628df032b82SMatthew G. Knepley     }
629df032b82SMatthew G. Knepley   }
630df032b82SMatthew G. Knepley   PetscFunctionReturn(0);
631df032b82SMatthew G. Knepley }
6327d282ae0SMichael Lange 
633de78e4feSLisandro Dalcin /*
634de78e4feSLisandro Dalcin $Entities
635de78e4feSLisandro Dalcin   numPoints(unsigned long) numCurves(unsigned long)
636de78e4feSLisandro Dalcin     numSurfaces(unsigned long) numVolumes(unsigned long)
637de78e4feSLisandro Dalcin   // points
638de78e4feSLisandro Dalcin   tag(int) boxMinX(double) boxMinY(double) boxMinZ(double)
639de78e4feSLisandro Dalcin     boxMaxX(double) boxMaxY(double) boxMaxZ(double)
640de78e4feSLisandro Dalcin     numPhysicals(unsigned long) phyisicalTag[...](int)
641de78e4feSLisandro Dalcin   ...
642de78e4feSLisandro Dalcin   // curves
643de78e4feSLisandro Dalcin   tag(int) boxMinX(double) boxMinY(double) boxMinZ(double)
644de78e4feSLisandro Dalcin      boxMaxX(double) boxMaxY(double) boxMaxZ(double)
645de78e4feSLisandro Dalcin      numPhysicals(unsigned long) physicalTag[...](int)
646de78e4feSLisandro Dalcin      numBREPVert(unsigned long) tagBREPVert[...](int)
647de78e4feSLisandro Dalcin   ...
648de78e4feSLisandro Dalcin   // surfaces
649de78e4feSLisandro Dalcin   tag(int) boxMinX(double) boxMinY(double) boxMinZ(double)
650de78e4feSLisandro Dalcin     boxMaxX(double) boxMaxY(double) boxMaxZ(double)
651de78e4feSLisandro Dalcin     numPhysicals(unsigned long) physicalTag[...](int)
652de78e4feSLisandro Dalcin     numBREPCurve(unsigned long) tagBREPCurve[...](int)
653de78e4feSLisandro Dalcin   ...
654de78e4feSLisandro Dalcin   // volumes
655de78e4feSLisandro Dalcin   tag(int) boxMinX(double) boxMinY(double) boxMinZ(double)
656de78e4feSLisandro Dalcin     boxMaxX(double) boxMaxY(double) boxMaxZ(double)
657de78e4feSLisandro Dalcin     numPhysicals(unsigned long) physicalTag[...](int)
658de78e4feSLisandro Dalcin     numBREPSurfaces(unsigned long) tagBREPSurfaces[...](int)
659de78e4feSLisandro Dalcin   ...
660de78e4feSLisandro Dalcin $EndEntities
661de78e4feSLisandro Dalcin */
6620598e1a2SLisandro Dalcin static PetscErrorCode GmshReadEntities_v40(GmshFile *gmsh, GmshMesh *mesh)
663de78e4feSLisandro Dalcin {
664698a79b9SLisandro Dalcin   PetscViewer    viewer = gmsh->viewer;
665698a79b9SLisandro Dalcin   PetscBool      byteSwap = gmsh->byteSwap;
666698a79b9SLisandro Dalcin   long           index, num, lbuf[4];
667730356f6SLisandro Dalcin   int            dim, eid, numTags, *ibuf, t;
668698a79b9SLisandro Dalcin   PetscInt       count[4], i;
669a5ba3d71SLisandro Dalcin   GmshEntity     *entity = NULL;
670de78e4feSLisandro Dalcin   PetscErrorCode ierr;
671de78e4feSLisandro Dalcin 
672de78e4feSLisandro Dalcin   PetscFunctionBegin;
673698a79b9SLisandro Dalcin   ierr = PetscViewerRead(viewer, lbuf, 4, NULL, PETSC_LONG);CHKERRQ(ierr);
674698a79b9SLisandro Dalcin   if (byteSwap) {ierr = PetscByteSwap(lbuf, PETSC_LONG, 4);CHKERRQ(ierr);}
675698a79b9SLisandro Dalcin   for (i = 0; i < 4; ++i) count[i] = lbuf[i];
6760598e1a2SLisandro Dalcin   ierr = GmshEntitiesCreate(count, &mesh->entities);CHKERRQ(ierr);
677de78e4feSLisandro Dalcin   for (dim = 0; dim < 4; ++dim) {
678730356f6SLisandro Dalcin     for (index = 0; index < count[dim]; ++index) {
679730356f6SLisandro Dalcin       ierr = PetscViewerRead(viewer, &eid, 1, NULL, PETSC_ENUM);CHKERRQ(ierr);
680730356f6SLisandro Dalcin       if (byteSwap) {ierr = PetscByteSwap(&eid, PETSC_ENUM, 1);CHKERRQ(ierr);}
6810598e1a2SLisandro Dalcin       ierr = GmshEntitiesAdd(mesh->entities, (PetscInt)index, dim, eid, &entity);CHKERRQ(ierr);
682de78e4feSLisandro Dalcin       ierr = PetscViewerRead(viewer, entity->bbox, 6, NULL, PETSC_DOUBLE);CHKERRQ(ierr);
683de78e4feSLisandro Dalcin       if (byteSwap) {ierr = PetscByteSwap(entity->bbox, PETSC_DOUBLE, 6);CHKERRQ(ierr);}
684de78e4feSLisandro Dalcin       ierr = PetscViewerRead(viewer, &num, 1, NULL, PETSC_LONG);CHKERRQ(ierr);
685de78e4feSLisandro Dalcin       if (byteSwap) {ierr = PetscByteSwap(&num, PETSC_LONG, 1);CHKERRQ(ierr);}
686698a79b9SLisandro Dalcin       ierr = GmshBufferGet(gmsh, num, sizeof(int), &ibuf);CHKERRQ(ierr);
687de78e4feSLisandro Dalcin       ierr = PetscViewerRead(viewer, ibuf, num, NULL, PETSC_ENUM);CHKERRQ(ierr);
688730356f6SLisandro Dalcin       if (byteSwap) {ierr = PetscByteSwap(ibuf, PETSC_ENUM, num);CHKERRQ(ierr);}
689de78e4feSLisandro Dalcin       entity->numTags = numTags = (int) PetscMin(num, 4);
690de78e4feSLisandro Dalcin       for (t = 0; t < numTags; ++t) entity->tags[t] = ibuf[t];
691de78e4feSLisandro Dalcin       if (dim == 0) continue;
692de78e4feSLisandro Dalcin       ierr = PetscViewerRead(viewer, &num, 1, NULL, PETSC_LONG);CHKERRQ(ierr);
693de78e4feSLisandro Dalcin       if (byteSwap) {ierr = PetscByteSwap(&num, PETSC_LONG, 1);CHKERRQ(ierr);}
694698a79b9SLisandro Dalcin       ierr = GmshBufferGet(gmsh, num, sizeof(int), &ibuf);CHKERRQ(ierr);
695de78e4feSLisandro Dalcin       ierr = PetscViewerRead(viewer, ibuf, num, NULL, PETSC_ENUM);CHKERRQ(ierr);
696730356f6SLisandro Dalcin       if (byteSwap) {ierr = PetscByteSwap(ibuf, PETSC_ENUM, num);CHKERRQ(ierr);}
697de78e4feSLisandro Dalcin     }
698de78e4feSLisandro Dalcin   }
699de78e4feSLisandro Dalcin   PetscFunctionReturn(0);
700de78e4feSLisandro Dalcin }
701de78e4feSLisandro Dalcin 
702de78e4feSLisandro Dalcin /*
703de78e4feSLisandro Dalcin $Nodes
704de78e4feSLisandro Dalcin   numEntityBlocks(unsigned long) numNodes(unsigned long)
705de78e4feSLisandro Dalcin   tagEntity(int) dimEntity(int) typeNode(int) numNodes(unsigned long)
706de78e4feSLisandro Dalcin     tag(int) x(double) y(double) z(double)
707de78e4feSLisandro Dalcin     ...
708de78e4feSLisandro Dalcin   ...
709de78e4feSLisandro Dalcin $EndNodes
710de78e4feSLisandro Dalcin */
7110598e1a2SLisandro Dalcin static PetscErrorCode GmshReadNodes_v40(GmshFile *gmsh, GmshMesh *mesh)
712de78e4feSLisandro Dalcin {
713698a79b9SLisandro Dalcin   PetscViewer    viewer = gmsh->viewer;
714698a79b9SLisandro Dalcin   PetscBool      byteSwap = gmsh->byteSwap;
7150598e1a2SLisandro Dalcin   long           block, node, n, numEntityBlocks, numTotalNodes, numNodes;
716de78e4feSLisandro Dalcin   int            info[3], nid;
7170598e1a2SLisandro Dalcin   GmshNodes      *nodes;
718de78e4feSLisandro Dalcin   PetscErrorCode ierr;
719de78e4feSLisandro Dalcin 
720de78e4feSLisandro Dalcin   PetscFunctionBegin;
721de78e4feSLisandro Dalcin   ierr = PetscViewerRead(viewer, &numEntityBlocks, 1, NULL, PETSC_LONG);CHKERRQ(ierr);
722de78e4feSLisandro Dalcin   if (byteSwap) {ierr = PetscByteSwap(&numEntityBlocks, PETSC_LONG, 1);CHKERRQ(ierr);}
723de78e4feSLisandro Dalcin   ierr = PetscViewerRead(viewer, &numTotalNodes, 1, NULL, PETSC_LONG);CHKERRQ(ierr);
724de78e4feSLisandro Dalcin   if (byteSwap) {ierr = PetscByteSwap(&numTotalNodes, PETSC_LONG, 1);CHKERRQ(ierr);}
7250598e1a2SLisandro Dalcin   ierr = GmshNodesCreate(numTotalNodes, &nodes);CHKERRQ(ierr);
7260598e1a2SLisandro Dalcin   mesh->numNodes = numTotalNodes;
7270598e1a2SLisandro Dalcin   mesh->nodelist = nodes;
7280598e1a2SLisandro Dalcin   for (n = 0, block = 0; block < numEntityBlocks; ++block) {
729de78e4feSLisandro Dalcin     ierr = PetscViewerRead(viewer, info, 3, NULL, PETSC_ENUM);CHKERRQ(ierr);
730de78e4feSLisandro Dalcin     ierr = PetscViewerRead(viewer, &numNodes, 1, NULL, PETSC_LONG);CHKERRQ(ierr);
731de78e4feSLisandro Dalcin     if (byteSwap) {ierr = PetscByteSwap(&numNodes, PETSC_LONG, 1);CHKERRQ(ierr);}
732698a79b9SLisandro Dalcin     if (gmsh->binary) {
733277f51e8SBarry Smith       size_t nbytes = sizeof(int) + 3*sizeof(double);
734277f51e8SBarry Smith       char   *cbuf = NULL; /* dummy value to prevent warning from compiler about possible unitilized value */
735698a79b9SLisandro Dalcin       ierr = GmshBufferGet(gmsh, numNodes, nbytes, &cbuf);CHKERRQ(ierr);
736de78e4feSLisandro Dalcin       ierr = PetscViewerRead(viewer, cbuf, numNodes*nbytes, NULL, PETSC_CHAR);CHKERRQ(ierr);
7370598e1a2SLisandro Dalcin       for (node = 0; node < numNodes; ++node, ++n) {
738de78e4feSLisandro Dalcin         char   *cnid = cbuf + node*nbytes, *cxyz = cnid + sizeof(int);
7390598e1a2SLisandro Dalcin         double *xyz = nodes->xyz + n*3;
74030815ce0SLisandro Dalcin         if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(cnid, PETSC_ENUM, 1);CHKERRQ(ierr);}
74130815ce0SLisandro Dalcin         if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(cxyz, PETSC_DOUBLE, 3);CHKERRQ(ierr);}
742de78e4feSLisandro Dalcin         ierr = PetscMemcpy(&nid, cnid, sizeof(int));CHKERRQ(ierr);
743de78e4feSLisandro Dalcin         ierr = PetscMemcpy(xyz, cxyz, 3*sizeof(double));CHKERRQ(ierr);
744de78e4feSLisandro Dalcin         if (byteSwap) {ierr = PetscByteSwap(&nid, PETSC_ENUM, 1);CHKERRQ(ierr);}
745de78e4feSLisandro Dalcin         if (byteSwap) {ierr = PetscByteSwap(xyz, PETSC_DOUBLE, 3);CHKERRQ(ierr);}
7460598e1a2SLisandro Dalcin         nodes->id[n] = nid;
747*81a1af93SMatthew G. Knepley         nodes->tag[n] = -1;
748de78e4feSLisandro Dalcin       }
749de78e4feSLisandro Dalcin     } else {
7500598e1a2SLisandro Dalcin       for (node = 0; node < numNodes; ++node, ++n) {
7510598e1a2SLisandro Dalcin         double *xyz = nodes->xyz + n*3;
752de78e4feSLisandro Dalcin         ierr = PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM);CHKERRQ(ierr);
753de78e4feSLisandro Dalcin         ierr = PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE);CHKERRQ(ierr);
7540598e1a2SLisandro Dalcin         if (byteSwap) {ierr = PetscByteSwap(&nid, PETSC_ENUM, 1);CHKERRQ(ierr);}
755de78e4feSLisandro Dalcin         if (byteSwap) {ierr = PetscByteSwap(xyz, PETSC_DOUBLE, 3);CHKERRQ(ierr);}
7560598e1a2SLisandro Dalcin         nodes->id[n] = nid;
757*81a1af93SMatthew G. Knepley         nodes->tag[n] = -1;
758de78e4feSLisandro Dalcin       }
759de78e4feSLisandro Dalcin     }
760de78e4feSLisandro Dalcin   }
761de78e4feSLisandro Dalcin   PetscFunctionReturn(0);
762de78e4feSLisandro Dalcin }
763de78e4feSLisandro Dalcin 
764de78e4feSLisandro Dalcin /*
765de78e4feSLisandro Dalcin $Elements
766de78e4feSLisandro Dalcin   numEntityBlocks(unsigned long) numElements(unsigned long)
767de78e4feSLisandro Dalcin   tagEntity(int) dimEntity(int) typeEle(int) numElements(unsigned long)
768de78e4feSLisandro Dalcin     tag(int) numVert[...](int)
769de78e4feSLisandro Dalcin     ...
770de78e4feSLisandro Dalcin   ...
771de78e4feSLisandro Dalcin $EndElements
772de78e4feSLisandro Dalcin */
7730598e1a2SLisandro Dalcin static PetscErrorCode GmshReadElements_v40(GmshFile *gmsh, GmshMesh *mesh)
774de78e4feSLisandro Dalcin {
775698a79b9SLisandro Dalcin   PetscViewer    viewer = gmsh->viewer;
776698a79b9SLisandro Dalcin   PetscBool      byteSwap = gmsh->byteSwap;
777de78e4feSLisandro Dalcin   long           c, block, numEntityBlocks, numTotalElements, elem, numElements;
778de78e4feSLisandro Dalcin   int            p, info[3], *ibuf = NULL;
7790598e1a2SLisandro Dalcin   int            eid, dim, cellType, numVerts, numNodes, numTags;
780a5ba3d71SLisandro Dalcin   GmshEntity     *entity = NULL;
781de78e4feSLisandro Dalcin   GmshElement    *elements;
7820598e1a2SLisandro Dalcin   PetscInt       *nodeMap = gmsh->nodeMap;
783de78e4feSLisandro Dalcin   PetscErrorCode ierr;
784de78e4feSLisandro Dalcin 
785de78e4feSLisandro Dalcin   PetscFunctionBegin;
786de78e4feSLisandro Dalcin   ierr = PetscViewerRead(viewer, &numEntityBlocks, 1, NULL, PETSC_LONG);CHKERRQ(ierr);
787de78e4feSLisandro Dalcin   if (byteSwap) {ierr = PetscByteSwap(&numEntityBlocks, PETSC_LONG, 1);CHKERRQ(ierr);}
788de78e4feSLisandro Dalcin   ierr = PetscViewerRead(viewer, &numTotalElements, 1, NULL, PETSC_LONG);CHKERRQ(ierr);
789de78e4feSLisandro Dalcin   if (byteSwap) {ierr = PetscByteSwap(&numTotalElements, PETSC_LONG, 1);CHKERRQ(ierr);}
7900598e1a2SLisandro Dalcin   ierr = GmshElementsCreate(numTotalElements, &elements);CHKERRQ(ierr);
7910598e1a2SLisandro Dalcin   mesh->numElems = numTotalElements;
7920598e1a2SLisandro Dalcin   mesh->elements = elements;
793de78e4feSLisandro Dalcin   for (c = 0, block = 0; block < numEntityBlocks; ++block) {
794de78e4feSLisandro Dalcin     ierr = PetscViewerRead(viewer, info, 3, NULL, PETSC_ENUM);CHKERRQ(ierr);
795de78e4feSLisandro Dalcin     if (byteSwap) {ierr = PetscByteSwap(info, PETSC_ENUM, 3);CHKERRQ(ierr);}
796de78e4feSLisandro Dalcin     eid = info[0]; dim = info[1]; cellType = info[2];
7970598e1a2SLisandro Dalcin     ierr = GmshEntitiesGet(mesh->entities, dim, eid, &entity);CHKERRQ(ierr);
7980598e1a2SLisandro Dalcin     ierr = GmshCellTypeCheck(cellType);CHKERRQ(ierr);
7990598e1a2SLisandro Dalcin     numVerts = GmshCellMap[cellType].numVerts;
8000598e1a2SLisandro Dalcin     numNodes = GmshCellMap[cellType].numNodes;
801730356f6SLisandro Dalcin     numTags  = entity->numTags;
802de78e4feSLisandro Dalcin     ierr = PetscViewerRead(viewer, &numElements, 1, NULL, PETSC_LONG);CHKERRQ(ierr);
803de78e4feSLisandro Dalcin     if (byteSwap) {ierr = PetscByteSwap(&numElements, PETSC_LONG, 1);CHKERRQ(ierr);}
804698a79b9SLisandro Dalcin     ierr = GmshBufferGet(gmsh, (1+numNodes)*numElements, sizeof(int), &ibuf);CHKERRQ(ierr);
805de78e4feSLisandro Dalcin     ierr = PetscViewerRead(viewer, ibuf, (1+numNodes)*numElements, NULL, PETSC_ENUM);CHKERRQ(ierr);
806de78e4feSLisandro Dalcin     if (byteSwap) {ierr = PetscByteSwap(ibuf, PETSC_ENUM, (1+numNodes)*numElements);CHKERRQ(ierr);}
807de78e4feSLisandro Dalcin     for (elem = 0; elem < numElements; ++elem, ++c) {
808de78e4feSLisandro Dalcin       GmshElement *element = elements + c;
8090598e1a2SLisandro Dalcin       const int *id = ibuf + elem*(1+numNodes), *nodes = id + 1;
8100598e1a2SLisandro Dalcin       element->id  = id[0];
811de78e4feSLisandro Dalcin       element->dim = dim;
812de78e4feSLisandro Dalcin       element->cellType = cellType;
8130598e1a2SLisandro Dalcin       element->numVerts = numVerts;
814de78e4feSLisandro Dalcin       element->numNodes = numNodes;
815de78e4feSLisandro Dalcin       element->numTags  = numTags;
8160598e1a2SLisandro Dalcin       ierr = PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes);CHKERRQ(ierr);
8170598e1a2SLisandro Dalcin       for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]];
8180598e1a2SLisandro Dalcin       for (p = 0; p < element->numTags;  p++) element->tags[p]  = entity->tags[p];
819de78e4feSLisandro Dalcin     }
820de78e4feSLisandro Dalcin   }
821698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
822698a79b9SLisandro Dalcin }
823698a79b9SLisandro Dalcin 
8240598e1a2SLisandro Dalcin static PetscErrorCode GmshReadPeriodic_v40(GmshFile *gmsh, PetscInt periodicMap[])
825698a79b9SLisandro Dalcin {
826698a79b9SLisandro Dalcin   PetscViewer    viewer = gmsh->viewer;
827698a79b9SLisandro Dalcin   int            fileFormat = gmsh->fileFormat;
828698a79b9SLisandro Dalcin   PetscBool      binary = gmsh->binary;
829698a79b9SLisandro Dalcin   PetscBool      byteSwap = gmsh->byteSwap;
830698a79b9SLisandro Dalcin   int            numPeriodic, snum, i;
831698a79b9SLisandro Dalcin   char           line[PETSC_MAX_PATH_LEN];
8320598e1a2SLisandro Dalcin   PetscInt       *nodeMap = gmsh->nodeMap;
833698a79b9SLisandro Dalcin   PetscErrorCode ierr;
834698a79b9SLisandro Dalcin 
835698a79b9SLisandro Dalcin   PetscFunctionBegin;
836698a79b9SLisandro Dalcin   if (fileFormat == 22 || !binary) {
837698a79b9SLisandro Dalcin     ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr);
838698a79b9SLisandro Dalcin     snum = sscanf(line, "%d", &numPeriodic);
8392c71b3e2SJacob Faibussowitsch     PetscCheckFalse(snum != 1,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
840698a79b9SLisandro Dalcin   } else {
841698a79b9SLisandro Dalcin     ierr = PetscViewerRead(viewer, &numPeriodic, 1, NULL, PETSC_ENUM);CHKERRQ(ierr);
842698a79b9SLisandro Dalcin     if (byteSwap) {ierr = PetscByteSwap(&numPeriodic, PETSC_ENUM, 1);CHKERRQ(ierr);}
843698a79b9SLisandro Dalcin   }
844698a79b9SLisandro Dalcin   for (i = 0; i < numPeriodic; i++) {
8459dddd249SSatish Balay     int    ibuf[3], correspondingDim = -1, correspondingTag = -1, primaryTag = -1, correspondingNode, primaryNode;
846698a79b9SLisandro Dalcin     long   j, nNodes;
847698a79b9SLisandro Dalcin     double affine[16];
848698a79b9SLisandro Dalcin 
849698a79b9SLisandro Dalcin     if (fileFormat == 22 || !binary) {
850698a79b9SLisandro Dalcin       ierr = PetscViewerRead(viewer, line, 3, NULL, PETSC_STRING);CHKERRQ(ierr);
8519dddd249SSatish Balay       snum = sscanf(line, "%d %d %d", &correspondingDim, &correspondingTag, &primaryTag);
8522c71b3e2SJacob Faibussowitsch       PetscCheckFalse(snum != 3,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
853698a79b9SLisandro Dalcin     } else {
854698a79b9SLisandro Dalcin       ierr = PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM);CHKERRQ(ierr);
855698a79b9SLisandro Dalcin       if (byteSwap) {ierr = PetscByteSwap(ibuf, PETSC_ENUM, 3);CHKERRQ(ierr);}
8569dddd249SSatish Balay       correspondingDim = ibuf[0]; correspondingTag = ibuf[1]; primaryTag = ibuf[2];
857698a79b9SLisandro Dalcin     }
8589dddd249SSatish Balay     (void)correspondingDim; (void)correspondingTag; (void)primaryTag; /* unused */
859698a79b9SLisandro Dalcin 
860698a79b9SLisandro Dalcin     if (fileFormat == 22 || !binary) {
861698a79b9SLisandro Dalcin       ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr);
862698a79b9SLisandro Dalcin       snum = sscanf(line, "%ld", &nNodes);
8634c500f23SPierre Jolivet       if (snum != 1) { /* discard transformation and try again */
864698a79b9SLisandro Dalcin         ierr = PetscViewerRead(viewer, line, -PETSC_MAX_PATH_LEN, NULL, PETSC_STRING);CHKERRQ(ierr);
865698a79b9SLisandro Dalcin         ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr);
866698a79b9SLisandro Dalcin         snum = sscanf(line, "%ld", &nNodes);
8672c71b3e2SJacob Faibussowitsch         PetscCheckFalse(snum != 1,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
868698a79b9SLisandro Dalcin       }
869698a79b9SLisandro Dalcin     } else {
870698a79b9SLisandro Dalcin       ierr = PetscViewerRead(viewer, &nNodes, 1, NULL, PETSC_LONG);CHKERRQ(ierr);
871698a79b9SLisandro Dalcin       if (byteSwap) {ierr = PetscByteSwap(&nNodes, PETSC_LONG, 1);CHKERRQ(ierr);}
8724c500f23SPierre Jolivet       if (nNodes == -1) { /* discard transformation and try again */
873698a79b9SLisandro Dalcin         ierr = PetscViewerRead(viewer, affine, 16, NULL, PETSC_DOUBLE);CHKERRQ(ierr);
874698a79b9SLisandro Dalcin         ierr = PetscViewerRead(viewer, &nNodes, 1, NULL, PETSC_LONG);CHKERRQ(ierr);
875698a79b9SLisandro Dalcin         if (byteSwap) {ierr = PetscByteSwap(&nNodes, PETSC_LONG, 1);CHKERRQ(ierr);}
876698a79b9SLisandro Dalcin       }
877698a79b9SLisandro Dalcin     }
878698a79b9SLisandro Dalcin 
879698a79b9SLisandro Dalcin     for (j = 0; j < nNodes; j++) {
880698a79b9SLisandro Dalcin       if (fileFormat == 22 || !binary) {
881698a79b9SLisandro Dalcin         ierr = PetscViewerRead(viewer, line, 2, NULL, PETSC_STRING);CHKERRQ(ierr);
8829dddd249SSatish Balay         snum = sscanf(line, "%d %d", &correspondingNode, &primaryNode);
8832c71b3e2SJacob Faibussowitsch         PetscCheckFalse(snum != 2,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
884698a79b9SLisandro Dalcin       } else {
885698a79b9SLisandro Dalcin         ierr = PetscViewerRead(viewer, ibuf, 2, NULL, PETSC_ENUM);CHKERRQ(ierr);
886698a79b9SLisandro Dalcin         if (byteSwap) {ierr = PetscByteSwap(ibuf, PETSC_ENUM, 2);CHKERRQ(ierr);}
8879dddd249SSatish Balay         correspondingNode = ibuf[0]; primaryNode = ibuf[1];
888698a79b9SLisandro Dalcin       }
8899dddd249SSatish Balay       correspondingNode  = (int) nodeMap[correspondingNode];
8909dddd249SSatish Balay       primaryNode = (int) nodeMap[primaryNode];
8919dddd249SSatish Balay       periodicMap[correspondingNode] = primaryNode;
892698a79b9SLisandro Dalcin     }
893698a79b9SLisandro Dalcin   }
894698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
895698a79b9SLisandro Dalcin }
896698a79b9SLisandro Dalcin 
8970598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
898698a79b9SLisandro Dalcin $Entities
899698a79b9SLisandro Dalcin   numPoints(size_t) numCurves(size_t)
900698a79b9SLisandro Dalcin     numSurfaces(size_t) numVolumes(size_t)
901698a79b9SLisandro Dalcin   pointTag(int) X(double) Y(double) Z(double)
902698a79b9SLisandro Dalcin     numPhysicalTags(size_t) physicalTag(int) ...
903698a79b9SLisandro Dalcin   ...
904698a79b9SLisandro Dalcin   curveTag(int) minX(double) minY(double) minZ(double)
905698a79b9SLisandro Dalcin     maxX(double) maxY(double) maxZ(double)
906698a79b9SLisandro Dalcin     numPhysicalTags(size_t) physicalTag(int) ...
907698a79b9SLisandro Dalcin     numBoundingPoints(size_t) pointTag(int) ...
908698a79b9SLisandro Dalcin   ...
909698a79b9SLisandro Dalcin   surfaceTag(int) minX(double) minY(double) minZ(double)
910698a79b9SLisandro Dalcin     maxX(double) maxY(double) maxZ(double)
911698a79b9SLisandro Dalcin     numPhysicalTags(size_t) physicalTag(int) ...
912698a79b9SLisandro Dalcin     numBoundingCurves(size_t) curveTag(int) ...
913698a79b9SLisandro Dalcin   ...
914698a79b9SLisandro Dalcin   volumeTag(int) minX(double) minY(double) minZ(double)
915698a79b9SLisandro Dalcin     maxX(double) maxY(double) maxZ(double)
916698a79b9SLisandro Dalcin     numPhysicalTags(size_t) physicalTag(int) ...
917698a79b9SLisandro Dalcin     numBoundngSurfaces(size_t) surfaceTag(int) ...
918698a79b9SLisandro Dalcin   ...
919698a79b9SLisandro Dalcin $EndEntities
920698a79b9SLisandro Dalcin */
9210598e1a2SLisandro Dalcin static PetscErrorCode GmshReadEntities_v41(GmshFile *gmsh, GmshMesh *mesh)
922698a79b9SLisandro Dalcin {
923698a79b9SLisandro Dalcin   PetscInt       count[4], index, numTags, i;
924698a79b9SLisandro Dalcin   int            dim, eid, *tags = NULL;
925698a79b9SLisandro Dalcin   GmshEntity     *entity = NULL;
926698a79b9SLisandro Dalcin   PetscErrorCode ierr;
927698a79b9SLisandro Dalcin 
928698a79b9SLisandro Dalcin   PetscFunctionBegin;
929698a79b9SLisandro Dalcin   ierr = GmshReadSize(gmsh, count, 4);CHKERRQ(ierr);
9300598e1a2SLisandro Dalcin   ierr = GmshEntitiesCreate(count, &mesh->entities);CHKERRQ(ierr);
931698a79b9SLisandro Dalcin   for (dim = 0; dim < 4; ++dim) {
932698a79b9SLisandro Dalcin     for (index = 0; index < count[dim]; ++index) {
933698a79b9SLisandro Dalcin       ierr = GmshReadInt(gmsh, &eid, 1);CHKERRQ(ierr);
9340598e1a2SLisandro Dalcin       ierr = GmshEntitiesAdd(mesh->entities, (PetscInt)index, dim, eid, &entity);CHKERRQ(ierr);
935698a79b9SLisandro Dalcin       ierr = GmshReadDouble(gmsh, entity->bbox, (dim == 0) ? 3 : 6);CHKERRQ(ierr);
936698a79b9SLisandro Dalcin       ierr = GmshReadSize(gmsh, &numTags, 1);CHKERRQ(ierr);
937698a79b9SLisandro Dalcin       ierr = GmshBufferGet(gmsh, numTags, sizeof(int), &tags);CHKERRQ(ierr);
938698a79b9SLisandro Dalcin       ierr = GmshReadInt(gmsh, tags, numTags);CHKERRQ(ierr);
939698a79b9SLisandro Dalcin       entity->numTags = PetscMin(numTags, 4);
940698a79b9SLisandro Dalcin       for (i = 0; i < entity->numTags; ++i) entity->tags[i] = tags[i];
941698a79b9SLisandro Dalcin       if (dim == 0) continue;
942698a79b9SLisandro Dalcin       ierr = GmshReadSize(gmsh, &numTags, 1);CHKERRQ(ierr);
943698a79b9SLisandro Dalcin       ierr = GmshBufferGet(gmsh, numTags, sizeof(int), &tags);CHKERRQ(ierr);
944698a79b9SLisandro Dalcin       ierr = GmshReadInt(gmsh, tags, numTags);CHKERRQ(ierr);
945*81a1af93SMatthew G. Knepley       /* Currently, we do not save the ids for the bounding entities */
946698a79b9SLisandro Dalcin     }
947698a79b9SLisandro Dalcin   }
948698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
949698a79b9SLisandro Dalcin }
950698a79b9SLisandro Dalcin 
95133a088b6SMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
952698a79b9SLisandro Dalcin $Nodes
953698a79b9SLisandro Dalcin   numEntityBlocks(size_t) numNodes(size_t)
954698a79b9SLisandro Dalcin     minNodeTag(size_t) maxNodeTag(size_t)
955698a79b9SLisandro Dalcin   entityDim(int) entityTag(int) parametric(int; 0 or 1) numNodesBlock(size_t)
956698a79b9SLisandro Dalcin     nodeTag(size_t)
957698a79b9SLisandro Dalcin     ...
958698a79b9SLisandro Dalcin     x(double) y(double) z(double)
959698a79b9SLisandro Dalcin        < u(double; if parametric and entityDim = 1 or entityDim = 2) >
960698a79b9SLisandro Dalcin        < v(double; if parametric and entityDim = 2) >
961698a79b9SLisandro Dalcin     ...
962698a79b9SLisandro Dalcin   ...
963698a79b9SLisandro Dalcin $EndNodes
964698a79b9SLisandro Dalcin */
9650598e1a2SLisandro Dalcin static PetscErrorCode GmshReadNodes_v41(GmshFile *gmsh, GmshMesh *mesh)
966698a79b9SLisandro Dalcin {
967*81a1af93SMatthew G. Knepley   int            info[3], dim, eid, parametric;
968*81a1af93SMatthew G. Knepley   PetscInt       sizes[4], numEntityBlocks, numTags, numNodes, numNodesBlock = 0, block, node, n;
969*81a1af93SMatthew G. Knepley   GmshEntity     *entity = NULL;
9700598e1a2SLisandro Dalcin   GmshNodes      *nodes;
971698a79b9SLisandro Dalcin   PetscErrorCode ierr;
972698a79b9SLisandro Dalcin 
973698a79b9SLisandro Dalcin   PetscFunctionBegin;
974698a79b9SLisandro Dalcin   ierr = GmshReadSize(gmsh, sizes, 4);CHKERRQ(ierr);
9750598e1a2SLisandro Dalcin   numEntityBlocks = sizes[0]; numNodes = sizes[1];
9760598e1a2SLisandro Dalcin   ierr = GmshNodesCreate(numNodes, &nodes);CHKERRQ(ierr);
9770598e1a2SLisandro Dalcin   mesh->numNodes = numNodes;
9780598e1a2SLisandro Dalcin   mesh->nodelist = nodes;
979698a79b9SLisandro Dalcin   for (block = 0, node = 0; block < numEntityBlocks; ++block, node += numNodesBlock) {
980698a79b9SLisandro Dalcin     ierr = GmshReadInt(gmsh, info, 3);CHKERRQ(ierr);
981*81a1af93SMatthew G. Knepley     dim = info[0]; eid = info[1]; parametric = info[2];
982*81a1af93SMatthew G. Knepley     ierr = GmshEntitiesGet(mesh->entities, dim, eid, &entity);CHKERRQ(ierr);
983*81a1af93SMatthew G. Knepley     numTags = PetscMin(1, entity->numTags);
984*81a1af93SMatthew G. Knepley     if (entity->numTags > 1) PetscInfo(NULL, "Entity %d has more than %d physical tags, assigning only the first to nodes", eid, 1);
985*81a1af93SMatthew G. Knepley     PetscCheck(!parametric, PETSC_COMM_SELF, PETSC_ERR_SUP, "Parametric coordinates not supported");
9860598e1a2SLisandro Dalcin     ierr = GmshReadSize(gmsh, &numNodesBlock, 1);CHKERRQ(ierr);
9870598e1a2SLisandro Dalcin     ierr = GmshReadSize(gmsh, nodes->id+node, numNodesBlock);CHKERRQ(ierr);
9880598e1a2SLisandro Dalcin     ierr = GmshReadDouble(gmsh, nodes->xyz+node*3, numNodesBlock*3);CHKERRQ(ierr);
989*81a1af93SMatthew G. Knepley     for (n = 0; n < numNodesBlock; ++n) nodes->tag[node+n] = numTags ? entity->tags[0] : -1;
990698a79b9SLisandro Dalcin   }
9910598e1a2SLisandro Dalcin   gmsh->nodeStart = sizes[2];
9920598e1a2SLisandro Dalcin   gmsh->nodeEnd   = sizes[3]+1;
993698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
994698a79b9SLisandro Dalcin }
995698a79b9SLisandro Dalcin 
99633a088b6SMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
997698a79b9SLisandro Dalcin $Elements
998698a79b9SLisandro Dalcin   numEntityBlocks(size_t) numElements(size_t)
999698a79b9SLisandro Dalcin     minElementTag(size_t) maxElementTag(size_t)
1000698a79b9SLisandro Dalcin   entityDim(int) entityTag(int) elementType(int; see below) numElementsBlock(size_t)
1001698a79b9SLisandro Dalcin     elementTag(size_t) nodeTag(size_t) ...
1002698a79b9SLisandro Dalcin     ...
1003698a79b9SLisandro Dalcin   ...
1004698a79b9SLisandro Dalcin $EndElements
1005698a79b9SLisandro Dalcin */
10060598e1a2SLisandro Dalcin static PetscErrorCode GmshReadElements_v41(GmshFile *gmsh, GmshMesh *mesh)
1007698a79b9SLisandro Dalcin {
10080598e1a2SLisandro Dalcin   int            info[3], eid, dim, cellType;
10090598e1a2SLisandro Dalcin   PetscInt       sizes[4], *ibuf = NULL, numEntityBlocks, numElements, numBlockElements, numVerts, numNodes, numTags, block, elem, c, p;
1010698a79b9SLisandro Dalcin   GmshEntity     *entity = NULL;
1011698a79b9SLisandro Dalcin   GmshElement    *elements;
10120598e1a2SLisandro Dalcin   PetscInt       *nodeMap = gmsh->nodeMap;
1013698a79b9SLisandro Dalcin   PetscErrorCode ierr;
1014698a79b9SLisandro Dalcin 
1015698a79b9SLisandro Dalcin   PetscFunctionBegin;
1016698a79b9SLisandro Dalcin   ierr = GmshReadSize(gmsh, sizes, 4);CHKERRQ(ierr);
1017698a79b9SLisandro Dalcin   numEntityBlocks = sizes[0]; numElements = sizes[1];
10180598e1a2SLisandro Dalcin   ierr = GmshElementsCreate(numElements, &elements);CHKERRQ(ierr);
10190598e1a2SLisandro Dalcin   mesh->numElems = numElements;
10200598e1a2SLisandro Dalcin   mesh->elements = elements;
1021698a79b9SLisandro Dalcin   for (c = 0, block = 0; block < numEntityBlocks; ++block) {
1022698a79b9SLisandro Dalcin     ierr = GmshReadInt(gmsh, info, 3);CHKERRQ(ierr);
1023698a79b9SLisandro Dalcin     dim = info[0]; eid = info[1]; cellType = info[2];
10240598e1a2SLisandro Dalcin     ierr = GmshEntitiesGet(mesh->entities, dim, eid, &entity);CHKERRQ(ierr);
10250598e1a2SLisandro Dalcin     ierr = GmshCellTypeCheck(cellType);CHKERRQ(ierr);
10260598e1a2SLisandro Dalcin     numVerts = GmshCellMap[cellType].numVerts;
10270598e1a2SLisandro Dalcin     numNodes = GmshCellMap[cellType].numNodes;
1028*81a1af93SMatthew G. Knepley     numTags  = PetscMin(4, entity->numTags);
1029*81a1af93SMatthew G. Knepley     if (entity->numTags > 4) PetscInfo(NULL, "Entity %d has more then %d physical tags, assigning only the first to elements", eid, 4);
1030698a79b9SLisandro Dalcin     ierr = GmshReadSize(gmsh, &numBlockElements, 1);CHKERRQ(ierr);
1031698a79b9SLisandro Dalcin     ierr = GmshBufferGet(gmsh, (1+numNodes)*numBlockElements, sizeof(PetscInt), &ibuf);CHKERRQ(ierr);
1032698a79b9SLisandro Dalcin     ierr = GmshReadSize(gmsh, ibuf, (1+numNodes)*numBlockElements);CHKERRQ(ierr);
1033698a79b9SLisandro Dalcin     for (elem = 0; elem < numBlockElements; ++elem, ++c) {
1034698a79b9SLisandro Dalcin       GmshElement *element = elements + c;
10350598e1a2SLisandro Dalcin       const PetscInt *id = ibuf + elem*(1+numNodes), *nodes = id + 1;
1036698a79b9SLisandro Dalcin       element->id  = id[0];
1037698a79b9SLisandro Dalcin       element->dim = dim;
1038698a79b9SLisandro Dalcin       element->cellType = cellType;
10390598e1a2SLisandro Dalcin       element->numVerts = numVerts;
1040698a79b9SLisandro Dalcin       element->numNodes = numNodes;
1041698a79b9SLisandro Dalcin       element->numTags  = numTags;
10420598e1a2SLisandro Dalcin       ierr = PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes);CHKERRQ(ierr);
10430598e1a2SLisandro Dalcin       for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]];
10440598e1a2SLisandro Dalcin       for (p = 0; p < element->numTags;  p++) element->tags[p]  = entity->tags[p];
1045698a79b9SLisandro Dalcin     }
1046698a79b9SLisandro Dalcin   }
1047698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
1048698a79b9SLisandro Dalcin }
1049698a79b9SLisandro Dalcin 
10500598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
1051698a79b9SLisandro Dalcin $Periodic
1052698a79b9SLisandro Dalcin   numPeriodicLinks(size_t)
10539dddd249SSatish Balay   entityDim(int) entityTag(int) entityTagPrimary(int)
1054698a79b9SLisandro Dalcin   numAffine(size_t) value(double) ...
1055698a79b9SLisandro Dalcin   numCorrespondingNodes(size_t)
10569dddd249SSatish Balay     nodeTag(size_t) nodeTagPrimary(size_t)
1057698a79b9SLisandro Dalcin     ...
1058698a79b9SLisandro Dalcin   ...
1059698a79b9SLisandro Dalcin $EndPeriodic
1060698a79b9SLisandro Dalcin */
10610598e1a2SLisandro Dalcin static PetscErrorCode GmshReadPeriodic_v41(GmshFile *gmsh, PetscInt periodicMap[])
1062698a79b9SLisandro Dalcin {
1063698a79b9SLisandro Dalcin   int            info[3];
1064698a79b9SLisandro Dalcin   double         dbuf[16];
10650598e1a2SLisandro Dalcin   PetscInt       numPeriodicLinks, numAffine, numCorrespondingNodes, *nodeTags = NULL, link, node;
10660598e1a2SLisandro Dalcin   PetscInt       *nodeMap = gmsh->nodeMap;
1067698a79b9SLisandro Dalcin   PetscErrorCode ierr;
1068698a79b9SLisandro Dalcin 
1069698a79b9SLisandro Dalcin   PetscFunctionBegin;
1070698a79b9SLisandro Dalcin   ierr = GmshReadSize(gmsh, &numPeriodicLinks, 1);CHKERRQ(ierr);
1071698a79b9SLisandro Dalcin   for (link = 0; link < numPeriodicLinks; ++link) {
1072698a79b9SLisandro Dalcin     ierr = GmshReadInt(gmsh, info, 3);CHKERRQ(ierr);
1073698a79b9SLisandro Dalcin     ierr = GmshReadSize(gmsh, &numAffine, 1);CHKERRQ(ierr);
1074698a79b9SLisandro Dalcin     ierr = GmshReadDouble(gmsh, dbuf, numAffine);CHKERRQ(ierr);
1075698a79b9SLisandro Dalcin     ierr = GmshReadSize(gmsh, &numCorrespondingNodes, 1);CHKERRQ(ierr);
1076698a79b9SLisandro Dalcin     ierr = GmshBufferGet(gmsh, numCorrespondingNodes, sizeof(PetscInt), &nodeTags);CHKERRQ(ierr);
1077698a79b9SLisandro Dalcin     ierr = GmshReadSize(gmsh, nodeTags, numCorrespondingNodes*2);CHKERRQ(ierr);
1078698a79b9SLisandro Dalcin     for (node = 0; node < numCorrespondingNodes; ++node) {
10799dddd249SSatish Balay       PetscInt correspondingNode = nodeMap[nodeTags[node*2+0]];
10809dddd249SSatish Balay       PetscInt primaryNode = nodeMap[nodeTags[node*2+1]];
10819dddd249SSatish Balay       periodicMap[correspondingNode] = primaryNode;
1082698a79b9SLisandro Dalcin     }
1083698a79b9SLisandro Dalcin   }
1084698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
1085698a79b9SLisandro Dalcin }
1086698a79b9SLisandro Dalcin 
10870598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
1088d6689ca9SLisandro Dalcin $MeshFormat // same as MSH version 2
1089d6689ca9SLisandro Dalcin   version(ASCII double; currently 4.1)
1090d6689ca9SLisandro Dalcin   file-type(ASCII int; 0 for ASCII mode, 1 for binary mode)
1091d6689ca9SLisandro Dalcin   data-size(ASCII int; sizeof(size_t))
1092d6689ca9SLisandro Dalcin   < int with value one; only in binary mode, to detect endianness >
1093d6689ca9SLisandro Dalcin $EndMeshFormat
1094d6689ca9SLisandro Dalcin */
10950598e1a2SLisandro Dalcin static PetscErrorCode GmshReadMeshFormat(GmshFile *gmsh)
1096698a79b9SLisandro Dalcin {
1097698a79b9SLisandro Dalcin   char           line[PETSC_MAX_PATH_LEN];
1098698a79b9SLisandro Dalcin   int            snum, fileType, fileFormat, dataSize, checkEndian;
1099698a79b9SLisandro Dalcin   float          version;
1100698a79b9SLisandro Dalcin   PetscErrorCode ierr;
1101698a79b9SLisandro Dalcin 
1102698a79b9SLisandro Dalcin   PetscFunctionBegin;
1103698a79b9SLisandro Dalcin   ierr = GmshReadString(gmsh, line, 3);CHKERRQ(ierr);
1104698a79b9SLisandro Dalcin   snum = sscanf(line, "%f %d %d", &version, &fileType, &dataSize);
11052c71b3e2SJacob Faibussowitsch   PetscCheckFalse(snum != 3,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line);
11062c71b3e2SJacob Faibussowitsch   PetscCheckFalse(version < 2.2,PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at least 2.2", (double)version);
11072c71b3e2SJacob Faibussowitsch   PetscCheckFalse((int)version == 3,PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f not supported", (double)version);
11082c71b3e2SJacob Faibussowitsch   PetscCheckFalse(version > 4.1,PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at most 4.1", (double)version);
11092c71b3e2SJacob Faibussowitsch   PetscCheckFalse(gmsh->binary && !fileType,PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Viewer is binary but Gmsh file is ASCII");
11102c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!gmsh->binary && fileType,PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Viewer is ASCII but Gmsh file is binary");
1111af7a0b9fSSatish Balay   fileFormat = (int)roundf(version*10);
11122c71b3e2SJacob Faibussowitsch   PetscCheckFalse(fileFormat <= 40 && dataSize != sizeof(double),PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Data size %d is not valid for a Gmsh file", dataSize);
11132c71b3e2SJacob Faibussowitsch   PetscCheckFalse(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);
1114698a79b9SLisandro Dalcin   gmsh->fileFormat = fileFormat;
1115698a79b9SLisandro Dalcin   gmsh->dataSize = dataSize;
1116698a79b9SLisandro Dalcin   gmsh->byteSwap = PETSC_FALSE;
1117698a79b9SLisandro Dalcin   if (gmsh->binary) {
1118698a79b9SLisandro Dalcin     ierr = GmshReadInt(gmsh, &checkEndian, 1);CHKERRQ(ierr);
1119698a79b9SLisandro Dalcin     if (checkEndian != 1) {
1120698a79b9SLisandro Dalcin       ierr = PetscByteSwap(&checkEndian, PETSC_ENUM, 1);CHKERRQ(ierr);
11212c71b3e2SJacob Faibussowitsch       PetscCheckFalse(checkEndian != 1,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to detect endianness in Gmsh file header: %s", line);
1122698a79b9SLisandro Dalcin       gmsh->byteSwap = PETSC_TRUE;
1123698a79b9SLisandro Dalcin     }
1124698a79b9SLisandro Dalcin   }
1125698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
1126698a79b9SLisandro Dalcin }
1127698a79b9SLisandro Dalcin 
11281f643af3SLisandro Dalcin /*
11291f643af3SLisandro Dalcin PhysicalNames
11301f643af3SLisandro Dalcin   numPhysicalNames(ASCII int)
11311f643af3SLisandro Dalcin   dimension(ASCII int) physicalTag(ASCII int) "name"(127 characters max)
11321f643af3SLisandro Dalcin   ...
11331f643af3SLisandro Dalcin $EndPhysicalNames
11341f643af3SLisandro Dalcin */
1135a45dabc8SMatthew G. Knepley static PetscErrorCode GmshReadPhysicalNames(GmshFile *gmsh, GmshMesh *mesh)
1136698a79b9SLisandro Dalcin {
11371f643af3SLisandro Dalcin   char           line[PETSC_MAX_PATH_LEN], name[128+2], *p, *q;
1138a45dabc8SMatthew G. Knepley   int            snum, region, dim, tag;
1139698a79b9SLisandro Dalcin   PetscErrorCode ierr;
1140698a79b9SLisandro Dalcin 
1141698a79b9SLisandro Dalcin   PetscFunctionBegin;
1142698a79b9SLisandro Dalcin   ierr = GmshReadString(gmsh, line, 1);CHKERRQ(ierr);
1143a45dabc8SMatthew G. Knepley   snum = sscanf(line, "%d", &region);
1144a45dabc8SMatthew G. Knepley   mesh->numRegions = region;
11452c71b3e2SJacob Faibussowitsch   PetscCheckFalse(snum != 1,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
1146a45dabc8SMatthew G. Knepley   ierr = PetscMalloc2(mesh->numRegions, &mesh->regionTags, mesh->numRegions, &mesh->regionNames);CHKERRQ(ierr);
1147a45dabc8SMatthew G. Knepley   for (region = 0; region < mesh->numRegions; ++region) {
11481f643af3SLisandro Dalcin     ierr = GmshReadString(gmsh, line, 2);CHKERRQ(ierr);
11491f643af3SLisandro Dalcin     snum = sscanf(line, "%d %d", &dim, &tag);
11502c71b3e2SJacob Faibussowitsch     PetscCheckFalse(snum != 2,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
11511f643af3SLisandro Dalcin     ierr = GmshReadString(gmsh, line, -(PetscInt)sizeof(line));CHKERRQ(ierr);
11521f643af3SLisandro Dalcin     ierr = PetscStrchr(line, '"', &p);CHKERRQ(ierr);
11532c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!p,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
11541f643af3SLisandro Dalcin     ierr = PetscStrrchr(line, '"', &q);CHKERRQ(ierr);
11552c71b3e2SJacob Faibussowitsch     PetscCheckFalse(q == p,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
11561f643af3SLisandro Dalcin     ierr = PetscStrncpy(name, p+1, (size_t)(q-p-1));CHKERRQ(ierr);
1157a45dabc8SMatthew G. Knepley     mesh->regionTags[region] = tag;
1158a45dabc8SMatthew G. Knepley     ierr = PetscStrallocpy(name, &mesh->regionNames[region]);CHKERRQ(ierr);
1159698a79b9SLisandro Dalcin   }
1160de78e4feSLisandro Dalcin   PetscFunctionReturn(0);
1161de78e4feSLisandro Dalcin }
1162de78e4feSLisandro Dalcin 
11630598e1a2SLisandro Dalcin static PetscErrorCode GmshReadEntities(GmshFile *gmsh, GmshMesh *mesh)
116496ca5757SLisandro Dalcin {
11650598e1a2SLisandro Dalcin   PetscErrorCode ierr;
11660598e1a2SLisandro Dalcin 
11670598e1a2SLisandro Dalcin   PetscFunctionBegin;
11680598e1a2SLisandro Dalcin   switch (gmsh->fileFormat) {
11690598e1a2SLisandro Dalcin   case 41: ierr = GmshReadEntities_v41(gmsh, mesh);CHKERRQ(ierr); break;
11700598e1a2SLisandro Dalcin   default: ierr = GmshReadEntities_v40(gmsh, mesh);CHKERRQ(ierr); break;
117196ca5757SLisandro Dalcin   }
11720598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
11730598e1a2SLisandro Dalcin }
11740598e1a2SLisandro Dalcin 
11750598e1a2SLisandro Dalcin static PetscErrorCode GmshReadNodes(GmshFile *gmsh, GmshMesh *mesh)
11760598e1a2SLisandro Dalcin {
11770598e1a2SLisandro Dalcin   PetscErrorCode ierr;
11780598e1a2SLisandro Dalcin 
11790598e1a2SLisandro Dalcin   PetscFunctionBegin;
11800598e1a2SLisandro Dalcin   switch (gmsh->fileFormat) {
11810598e1a2SLisandro Dalcin   case 41: ierr = GmshReadNodes_v41(gmsh, mesh);CHKERRQ(ierr); break;
11820598e1a2SLisandro Dalcin   case 40: ierr = GmshReadNodes_v40(gmsh, mesh);CHKERRQ(ierr); break;
11830598e1a2SLisandro Dalcin   default: ierr = GmshReadNodes_v22(gmsh, mesh);CHKERRQ(ierr); break;
11840598e1a2SLisandro Dalcin   }
11850598e1a2SLisandro Dalcin 
11860598e1a2SLisandro Dalcin   { /* Gmsh v2.2/v4.0 does not provide min/max node tags */
11870598e1a2SLisandro Dalcin     if (mesh->numNodes > 0 && gmsh->nodeEnd >= gmsh->nodeStart) {
11880598e1a2SLisandro Dalcin       PetscInt  tagMin = PETSC_MAX_INT, tagMax = PETSC_MIN_INT, n;
11890598e1a2SLisandro Dalcin       GmshNodes *nodes = mesh->nodelist;
11900598e1a2SLisandro Dalcin       for (n = 0; n < mesh->numNodes; ++n) {
11910598e1a2SLisandro Dalcin         const PetscInt tag = nodes->id[n];
11920598e1a2SLisandro Dalcin         tagMin = PetscMin(tag, tagMin);
11930598e1a2SLisandro Dalcin         tagMax = PetscMax(tag, tagMax);
11940598e1a2SLisandro Dalcin       }
11950598e1a2SLisandro Dalcin       gmsh->nodeStart = tagMin;
11960598e1a2SLisandro Dalcin       gmsh->nodeEnd   = tagMax+1;
11970598e1a2SLisandro Dalcin     }
11980598e1a2SLisandro Dalcin   }
11990598e1a2SLisandro Dalcin 
12000598e1a2SLisandro Dalcin   { /* Support for sparse node tags */
12010598e1a2SLisandro Dalcin     PetscInt  n, t;
12020598e1a2SLisandro Dalcin     GmshNodes *nodes = mesh->nodelist;
12030598e1a2SLisandro Dalcin     ierr = PetscMalloc1(gmsh->nodeEnd - gmsh->nodeStart, &gmsh->nbuf);CHKERRQ(ierr);
12040598e1a2SLisandro Dalcin     for (t = 0; t < gmsh->nodeEnd - gmsh->nodeStart; ++t) gmsh->nbuf[t] = PETSC_MIN_INT;
12050598e1a2SLisandro Dalcin     gmsh->nodeMap = gmsh->nbuf - gmsh->nodeStart;
12060598e1a2SLisandro Dalcin     for (n = 0; n < mesh->numNodes; ++n) {
12070598e1a2SLisandro Dalcin       const PetscInt tag = nodes->id[n];
12082c71b3e2SJacob Faibussowitsch       PetscCheckFalse(gmsh->nodeMap[tag] >= 0,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Repeated node tag %D", tag);
12090598e1a2SLisandro Dalcin       gmsh->nodeMap[tag] = n;
12100598e1a2SLisandro Dalcin     }
12110598e1a2SLisandro Dalcin   }
12120598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
12130598e1a2SLisandro Dalcin }
12140598e1a2SLisandro Dalcin 
12150598e1a2SLisandro Dalcin static PetscErrorCode GmshReadElements(GmshFile *gmsh, GmshMesh *mesh)
12160598e1a2SLisandro Dalcin {
12170598e1a2SLisandro Dalcin   PetscErrorCode ierr;
12180598e1a2SLisandro Dalcin 
12190598e1a2SLisandro Dalcin   PetscFunctionBegin;
12200598e1a2SLisandro Dalcin   switch (gmsh->fileFormat) {
12210598e1a2SLisandro Dalcin   case 41: ierr = GmshReadElements_v41(gmsh, mesh);CHKERRQ(ierr); break;
12220598e1a2SLisandro Dalcin   case 40: ierr = GmshReadElements_v40(gmsh, mesh);CHKERRQ(ierr); break;
12230598e1a2SLisandro Dalcin   default: ierr = GmshReadElements_v22(gmsh, mesh);CHKERRQ(ierr); break;
12240598e1a2SLisandro Dalcin   }
12250598e1a2SLisandro Dalcin 
12260598e1a2SLisandro Dalcin   { /* Reorder elements by codimension and polytope type */
12270598e1a2SLisandro Dalcin     PetscInt    ne = mesh->numElems;
12280598e1a2SLisandro Dalcin     GmshElement *elements = mesh->elements;
1229066ea43fSLisandro Dalcin     PetscInt    keymap[GMSH_NUM_POLYTOPES], nk = 0;
1230066ea43fSLisandro Dalcin     PetscInt    offset[GMSH_NUM_POLYTOPES+1], e, k;
12310598e1a2SLisandro Dalcin 
1232066ea43fSLisandro Dalcin     for (k = 0; k < GMSH_NUM_POLYTOPES; ++k) keymap[k] = PETSC_MIN_INT;
12330598e1a2SLisandro Dalcin     ierr = PetscMemzero(offset,sizeof(offset));CHKERRQ(ierr);
12340598e1a2SLisandro Dalcin 
1235066ea43fSLisandro Dalcin     keymap[GMSH_TET] = nk++;
1236066ea43fSLisandro Dalcin     keymap[GMSH_HEX] = nk++;
1237066ea43fSLisandro Dalcin     keymap[GMSH_PRI] = nk++;
1238066ea43fSLisandro Dalcin     keymap[GMSH_PYR] = nk++;
1239066ea43fSLisandro Dalcin     keymap[GMSH_TRI] = nk++;
1240066ea43fSLisandro Dalcin     keymap[GMSH_QUA] = nk++;
1241066ea43fSLisandro Dalcin     keymap[GMSH_SEG] = nk++;
1242066ea43fSLisandro Dalcin     keymap[GMSH_VTX] = nk++;
12430598e1a2SLisandro Dalcin 
12440598e1a2SLisandro Dalcin     ierr = GmshElementsCreate(mesh->numElems, &mesh->elements);CHKERRQ(ierr);
12450598e1a2SLisandro Dalcin #define key(eid) keymap[GmshCellMap[elements[(eid)].cellType].polytope]
12460598e1a2SLisandro Dalcin     for (e = 0; e < ne; ++e) offset[1+key(e)]++;
12470598e1a2SLisandro Dalcin     for (k = 1; k < nk; ++k) offset[k] += offset[k-1];
12480598e1a2SLisandro Dalcin     for (e = 0; e < ne; ++e) mesh->elements[offset[key(e)]++] = elements[e];
12490598e1a2SLisandro Dalcin #undef key
12500598e1a2SLisandro Dalcin     ierr = GmshElementsDestroy(&elements);CHKERRQ(ierr);
1251066ea43fSLisandro Dalcin   }
12520598e1a2SLisandro Dalcin 
1253066ea43fSLisandro Dalcin   { /* Mesh dimension and order */
1254066ea43fSLisandro Dalcin     GmshElement *elem = mesh->numElems ? mesh->elements : NULL;
1255066ea43fSLisandro Dalcin     mesh->dim   = elem ? GmshCellMap[elem->cellType].dim   : 0;
1256066ea43fSLisandro Dalcin     mesh->order = elem ? GmshCellMap[elem->cellType].order : 0;
12570598e1a2SLisandro Dalcin   }
12580598e1a2SLisandro Dalcin 
12590598e1a2SLisandro Dalcin   {
12600598e1a2SLisandro Dalcin     PetscBT  vtx;
12610598e1a2SLisandro Dalcin     PetscInt dim = mesh->dim, e, n, v;
12620598e1a2SLisandro Dalcin 
12630598e1a2SLisandro Dalcin     ierr = PetscBTCreate(mesh->numNodes, &vtx);CHKERRQ(ierr);
12640598e1a2SLisandro Dalcin 
12650598e1a2SLisandro Dalcin     /* Compute number of cells and set of vertices */
12660598e1a2SLisandro Dalcin     mesh->numCells = 0;
12670598e1a2SLisandro Dalcin     for (e = 0; e < mesh->numElems; ++e) {
12680598e1a2SLisandro Dalcin       GmshElement *elem = mesh->elements + e;
12690598e1a2SLisandro Dalcin       if (elem->dim == dim && dim > 0) mesh->numCells++;
12700598e1a2SLisandro Dalcin       for (v = 0; v < elem->numVerts; v++) {
12710598e1a2SLisandro Dalcin         ierr = PetscBTSet(vtx, elem->nodes[v]);CHKERRQ(ierr);
12720598e1a2SLisandro Dalcin       }
12730598e1a2SLisandro Dalcin     }
12740598e1a2SLisandro Dalcin 
12750598e1a2SLisandro Dalcin     /* Compute numbering for vertices */
12760598e1a2SLisandro Dalcin     mesh->numVerts = 0;
12770598e1a2SLisandro Dalcin     ierr = PetscMalloc1(mesh->numNodes, &mesh->vertexMap);CHKERRQ(ierr);
12780598e1a2SLisandro Dalcin     for (n = 0; n < mesh->numNodes; ++n)
12790598e1a2SLisandro Dalcin       mesh->vertexMap[n] = PetscBTLookup(vtx, n) ? mesh->numVerts++ : PETSC_MIN_INT;
12800598e1a2SLisandro Dalcin 
12810598e1a2SLisandro Dalcin     ierr = PetscBTDestroy(&vtx);CHKERRQ(ierr);
12820598e1a2SLisandro Dalcin   }
12830598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
12840598e1a2SLisandro Dalcin }
12850598e1a2SLisandro Dalcin 
12860598e1a2SLisandro Dalcin static PetscErrorCode GmshReadPeriodic(GmshFile *gmsh, GmshMesh *mesh)
12870598e1a2SLisandro Dalcin {
12880598e1a2SLisandro Dalcin   PetscInt       n;
12890598e1a2SLisandro Dalcin   PetscErrorCode ierr;
12900598e1a2SLisandro Dalcin 
12910598e1a2SLisandro Dalcin   PetscFunctionBegin;
12920598e1a2SLisandro Dalcin   ierr = PetscMalloc1(mesh->numNodes, &mesh->periodMap);CHKERRQ(ierr);
12930598e1a2SLisandro Dalcin   for (n = 0; n < mesh->numNodes; ++n) mesh->periodMap[n] = n;
12940598e1a2SLisandro Dalcin   switch (gmsh->fileFormat) {
12950598e1a2SLisandro Dalcin   case 41: ierr = GmshReadPeriodic_v41(gmsh, mesh->periodMap);CHKERRQ(ierr); break;
12960598e1a2SLisandro Dalcin   default: ierr = GmshReadPeriodic_v40(gmsh, mesh->periodMap);CHKERRQ(ierr); break;
12970598e1a2SLisandro Dalcin   }
12980598e1a2SLisandro Dalcin 
12999dddd249SSatish Balay   /* Find canonical primary nodes */
13000598e1a2SLisandro Dalcin   for (n = 0; n < mesh->numNodes; ++n)
13010598e1a2SLisandro Dalcin     while (mesh->periodMap[n] != mesh->periodMap[mesh->periodMap[n]])
13020598e1a2SLisandro Dalcin       mesh->periodMap[n] = mesh->periodMap[mesh->periodMap[n]];
13030598e1a2SLisandro Dalcin 
13049dddd249SSatish Balay   /* Renumber vertices (filter out correspondings) */
13050598e1a2SLisandro Dalcin   mesh->numVerts = 0;
13060598e1a2SLisandro Dalcin   for (n = 0; n < mesh->numNodes; ++n)
13070598e1a2SLisandro Dalcin     if (mesh->vertexMap[n] >= 0)   /* is vertex */
13089dddd249SSatish Balay       if (mesh->periodMap[n] == n) /* is primary */
13090598e1a2SLisandro Dalcin         mesh->vertexMap[n] = mesh->numVerts++;
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 corresponding  */
13130598e1a2SLisandro Dalcin         mesh->vertexMap[n] = mesh->vertexMap[mesh->periodMap[n]];
13140598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
13150598e1a2SLisandro Dalcin }
13160598e1a2SLisandro Dalcin 
1317066ea43fSLisandro Dalcin #define DM_POLYTOPE_VERTEX  DM_POLYTOPE_POINT
1318066ea43fSLisandro Dalcin #define DM_POLYTOPE_PYRAMID DM_POLYTOPE_UNKNOWN
1319066ea43fSLisandro Dalcin static const DMPolytopeType DMPolytopeMap[] = {
1320066ea43fSLisandro Dalcin   /* GMSH_VTX */ DM_POLYTOPE_VERTEX,
1321066ea43fSLisandro Dalcin   /* GMSH_SEG */ DM_POLYTOPE_SEGMENT,
1322066ea43fSLisandro Dalcin   /* GMSH_TRI */ DM_POLYTOPE_TRIANGLE,
1323066ea43fSLisandro Dalcin   /* GMSH_QUA */ DM_POLYTOPE_QUADRILATERAL,
1324066ea43fSLisandro Dalcin   /* GMSH_TET */ DM_POLYTOPE_TETRAHEDRON,
1325066ea43fSLisandro Dalcin   /* GMSH_HEX */ DM_POLYTOPE_HEXAHEDRON,
1326066ea43fSLisandro Dalcin   /* GMSH_PRI */ DM_POLYTOPE_TRI_PRISM,
1327066ea43fSLisandro Dalcin   /* GMSH_PYR */ DM_POLYTOPE_PYRAMID,
1328066ea43fSLisandro Dalcin   DM_POLYTOPE_UNKNOWN
1329066ea43fSLisandro Dalcin };
13300598e1a2SLisandro Dalcin 
13319fbee547SJacob Faibussowitsch static inline DMPolytopeType DMPolytopeTypeFromGmsh(PetscInt cellType)
13320598e1a2SLisandro Dalcin {
1333066ea43fSLisandro Dalcin   return DMPolytopeMap[GmshCellMap[cellType].polytope];
1334066ea43fSLisandro Dalcin }
1335066ea43fSLisandro Dalcin 
1336066ea43fSLisandro Dalcin static PetscErrorCode GmshCreateFE(MPI_Comm comm, const char prefix[], PetscBool isSimplex, PetscBool continuity, PetscDTNodeType nodeType, PetscInt dim, PetscInt Nc, PetscInt k, PetscFE *fem)
1337066ea43fSLisandro Dalcin {
1338066ea43fSLisandro Dalcin   DM              K;
1339066ea43fSLisandro Dalcin   PetscSpace      P;
1340066ea43fSLisandro Dalcin   PetscDualSpace  Q;
1341066ea43fSLisandro Dalcin   PetscQuadrature q, fq;
1342066ea43fSLisandro Dalcin   PetscBool       isTensor = isSimplex ? PETSC_FALSE : PETSC_TRUE;
1343066ea43fSLisandro Dalcin   PetscBool       endpoint = PETSC_TRUE;
1344066ea43fSLisandro Dalcin   char            name[32];
1345066ea43fSLisandro Dalcin   PetscErrorCode  ierr;
1346066ea43fSLisandro Dalcin 
1347066ea43fSLisandro Dalcin   PetscFunctionBegin;
1348066ea43fSLisandro Dalcin   /* Create space */
1349066ea43fSLisandro Dalcin   ierr = PetscSpaceCreate(comm, &P);CHKERRQ(ierr);
1350066ea43fSLisandro Dalcin   ierr = PetscSpaceSetType(P, PETSCSPACEPOLYNOMIAL);CHKERRQ(ierr);
1351066ea43fSLisandro Dalcin   ierr = PetscSpacePolynomialSetTensor(P, isTensor);CHKERRQ(ierr);
1352066ea43fSLisandro Dalcin   ierr = PetscSpaceSetNumComponents(P, Nc);CHKERRQ(ierr);
1353066ea43fSLisandro Dalcin   ierr = PetscSpaceSetNumVariables(P, dim);CHKERRQ(ierr);
1354066ea43fSLisandro Dalcin   ierr = PetscSpaceSetDegree(P, k, PETSC_DETERMINE);CHKERRQ(ierr);
1355066ea43fSLisandro Dalcin   if (prefix) {
1356066ea43fSLisandro Dalcin     ierr = PetscObjectSetOptionsPrefix((PetscObject) P, prefix);CHKERRQ(ierr);
1357066ea43fSLisandro Dalcin     ierr = PetscSpaceSetFromOptions(P);CHKERRQ(ierr);
1358066ea43fSLisandro Dalcin     ierr = PetscObjectSetOptionsPrefix((PetscObject) P, NULL);CHKERRQ(ierr);
1359066ea43fSLisandro Dalcin     ierr = PetscSpaceGetDegree(P, &k, NULL);CHKERRQ(ierr);
1360066ea43fSLisandro Dalcin   }
1361066ea43fSLisandro Dalcin   ierr = PetscSpaceSetUp(P);CHKERRQ(ierr);
1362066ea43fSLisandro Dalcin   /* Create dual space */
1363066ea43fSLisandro Dalcin   ierr = PetscDualSpaceCreate(comm, &Q);CHKERRQ(ierr);
1364066ea43fSLisandro Dalcin   ierr = PetscDualSpaceSetType(Q, PETSCDUALSPACELAGRANGE);CHKERRQ(ierr);
1365066ea43fSLisandro Dalcin   ierr = PetscDualSpaceLagrangeSetTensor(Q, isTensor);CHKERRQ(ierr);
1366066ea43fSLisandro Dalcin   ierr = PetscDualSpaceLagrangeSetContinuity(Q, continuity);CHKERRQ(ierr);
1367066ea43fSLisandro Dalcin   ierr = PetscDualSpaceLagrangeSetNodeType(Q, nodeType, endpoint, 0);CHKERRQ(ierr);
1368066ea43fSLisandro Dalcin   ierr = PetscDualSpaceSetNumComponents(Q, Nc);CHKERRQ(ierr);
1369066ea43fSLisandro Dalcin   ierr = PetscDualSpaceSetOrder(Q, k);CHKERRQ(ierr);
1370f783ec47SMatthew G. Knepley   ierr = DMPlexCreateReferenceCell(PETSC_COMM_SELF, DMPolytopeTypeSimpleShape(dim, isSimplex), &K);CHKERRQ(ierr);
1371066ea43fSLisandro Dalcin   ierr = PetscDualSpaceSetDM(Q, K);CHKERRQ(ierr);
1372066ea43fSLisandro Dalcin   ierr = DMDestroy(&K);CHKERRQ(ierr);
1373066ea43fSLisandro Dalcin   if (prefix) {
1374066ea43fSLisandro Dalcin     ierr = PetscObjectSetOptionsPrefix((PetscObject) Q, prefix);CHKERRQ(ierr);
1375066ea43fSLisandro Dalcin     ierr = PetscDualSpaceSetFromOptions(Q);CHKERRQ(ierr);
1376066ea43fSLisandro Dalcin     ierr = PetscObjectSetOptionsPrefix((PetscObject) Q, NULL);CHKERRQ(ierr);
1377066ea43fSLisandro Dalcin   }
1378066ea43fSLisandro Dalcin   ierr = PetscDualSpaceSetUp(Q);CHKERRQ(ierr);
1379066ea43fSLisandro Dalcin   /* Create quadrature */
1380066ea43fSLisandro Dalcin   if (isSimplex) {
1381066ea43fSLisandro Dalcin     ierr = PetscDTStroudConicalQuadrature(dim,   1, k+1, -1, +1, &q);CHKERRQ(ierr);
1382066ea43fSLisandro Dalcin     ierr = PetscDTStroudConicalQuadrature(dim-1, 1, k+1, -1, +1, &fq);CHKERRQ(ierr);
1383066ea43fSLisandro Dalcin   } else {
1384066ea43fSLisandro Dalcin     ierr = PetscDTGaussTensorQuadrature(dim,   1, k+1, -1, +1, &q);CHKERRQ(ierr);
1385066ea43fSLisandro Dalcin     ierr = PetscDTGaussTensorQuadrature(dim-1, 1, k+1, -1, +1, &fq);CHKERRQ(ierr);
1386066ea43fSLisandro Dalcin   }
1387066ea43fSLisandro Dalcin   /* Create finite element */
1388066ea43fSLisandro Dalcin   ierr = PetscFECreate(comm, fem);CHKERRQ(ierr);
1389066ea43fSLisandro Dalcin   ierr = PetscFESetType(*fem, PETSCFEBASIC);CHKERRQ(ierr);
1390066ea43fSLisandro Dalcin   ierr = PetscFESetNumComponents(*fem, Nc);CHKERRQ(ierr);
1391066ea43fSLisandro Dalcin   ierr = PetscFESetBasisSpace(*fem, P);CHKERRQ(ierr);
1392066ea43fSLisandro Dalcin   ierr = PetscFESetDualSpace(*fem, Q);CHKERRQ(ierr);
1393066ea43fSLisandro Dalcin   ierr = PetscFESetQuadrature(*fem, q);CHKERRQ(ierr);
1394066ea43fSLisandro Dalcin   ierr = PetscFESetFaceQuadrature(*fem, fq);CHKERRQ(ierr);
1395066ea43fSLisandro Dalcin   if (prefix) {
1396066ea43fSLisandro Dalcin     ierr = PetscObjectSetOptionsPrefix((PetscObject) *fem, prefix);CHKERRQ(ierr);
1397066ea43fSLisandro Dalcin     ierr = PetscFESetFromOptions(*fem);CHKERRQ(ierr);
1398066ea43fSLisandro Dalcin     ierr = PetscObjectSetOptionsPrefix((PetscObject) *fem, NULL);CHKERRQ(ierr);
1399066ea43fSLisandro Dalcin   }
1400066ea43fSLisandro Dalcin   ierr = PetscFESetUp(*fem);CHKERRQ(ierr);
1401066ea43fSLisandro Dalcin   /* Cleanup */
1402066ea43fSLisandro Dalcin   ierr = PetscSpaceDestroy(&P);CHKERRQ(ierr);
1403066ea43fSLisandro Dalcin   ierr = PetscDualSpaceDestroy(&Q);CHKERRQ(ierr);
1404066ea43fSLisandro Dalcin   ierr = PetscQuadratureDestroy(&q);CHKERRQ(ierr);
1405066ea43fSLisandro Dalcin   ierr = PetscQuadratureDestroy(&fq);CHKERRQ(ierr);
1406066ea43fSLisandro Dalcin   /* Set finite element name */
1407066ea43fSLisandro Dalcin   ierr = PetscSNPrintf(name, sizeof(name), "%s%D", isSimplex? "P" : "Q", k);CHKERRQ(ierr);
1408066ea43fSLisandro Dalcin   ierr = PetscFESetName(*fem, name);CHKERRQ(ierr);
1409066ea43fSLisandro Dalcin   PetscFunctionReturn(0);
141096ca5757SLisandro Dalcin }
141196ca5757SLisandro Dalcin 
1412d6689ca9SLisandro Dalcin /*@C
1413d6689ca9SLisandro Dalcin   DMPlexCreateGmshFromFile - Create a DMPlex mesh from a Gmsh file
1414d6689ca9SLisandro Dalcin 
1415d6689ca9SLisandro Dalcin + comm        - The MPI communicator
1416d6689ca9SLisandro Dalcin . filename    - Name of the Gmsh file
1417d6689ca9SLisandro Dalcin - interpolate - Create faces and edges in the mesh
1418d6689ca9SLisandro Dalcin 
1419d6689ca9SLisandro Dalcin   Output Parameter:
1420d6689ca9SLisandro Dalcin . dm  - The DM object representing the mesh
1421d6689ca9SLisandro Dalcin 
1422d6689ca9SLisandro Dalcin   Level: beginner
1423d6689ca9SLisandro Dalcin 
1424d6689ca9SLisandro Dalcin .seealso: DMPlexCreateFromFile(), DMPlexCreateGmsh(), DMPlexCreate()
1425d6689ca9SLisandro Dalcin @*/
1426d6689ca9SLisandro Dalcin PetscErrorCode DMPlexCreateGmshFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm)
1427d6689ca9SLisandro Dalcin {
1428d6689ca9SLisandro Dalcin   PetscViewer     viewer;
1429d6689ca9SLisandro Dalcin   PetscMPIInt     rank;
1430d6689ca9SLisandro Dalcin   int             fileType;
1431d6689ca9SLisandro Dalcin   PetscViewerType vtype;
1432d6689ca9SLisandro Dalcin   PetscErrorCode  ierr;
1433d6689ca9SLisandro Dalcin 
1434d6689ca9SLisandro Dalcin   PetscFunctionBegin;
1435ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
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;
1443d6689ca9SLisandro Dalcin 
1444580bdb30SBarry Smith     ierr = PetscArrayzero(gmsh,1);CHKERRQ(ierr);
1445d6689ca9SLisandro Dalcin     ierr = PetscViewerCreate(PETSC_COMM_SELF, &gmsh->viewer);CHKERRQ(ierr);
1446d6689ca9SLisandro Dalcin     ierr = PetscViewerSetType(gmsh->viewer, PETSCVIEWERASCII);CHKERRQ(ierr);
1447d6689ca9SLisandro Dalcin     ierr = PetscViewerFileSetMode(gmsh->viewer, FILE_MODE_READ);CHKERRQ(ierr);
1448d6689ca9SLisandro Dalcin     ierr = PetscViewerFileSetName(gmsh->viewer, filename);CHKERRQ(ierr);
1449d6689ca9SLisandro Dalcin     /* Read only the first two lines of the Gmsh file */
1450d6689ca9SLisandro Dalcin     ierr = GmshReadSection(gmsh, line);CHKERRQ(ierr);
1451d6689ca9SLisandro Dalcin     ierr = GmshExpect(gmsh, "$MeshFormat", line);CHKERRQ(ierr);
1452d6689ca9SLisandro Dalcin     ierr = GmshReadString(gmsh, line, 2);CHKERRQ(ierr);
1453d6689ca9SLisandro Dalcin     snum = sscanf(line, "%f %d", &version, &fileType);
14542c71b3e2SJacob Faibussowitsch     PetscCheckFalse(snum != 2,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line);
14552c71b3e2SJacob Faibussowitsch     PetscCheckFalse(version < 2.2,PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at least 2.2", (double)version);
14562c71b3e2SJacob Faibussowitsch     PetscCheckFalse((int)version == 3,PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f not supported", (double)version);
14572c71b3e2SJacob Faibussowitsch     PetscCheckFalse(version > 4.1,PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at most 4.1", (double)version);
1458d6689ca9SLisandro Dalcin     ierr = PetscViewerDestroy(&gmsh->viewer);CHKERRQ(ierr);
1459d6689ca9SLisandro Dalcin   }
1460ffc4695bSBarry Smith   ierr = MPI_Bcast(&fileType, 1, MPI_INT, 0, comm);CHKERRMPI(ierr);
1461d6689ca9SLisandro Dalcin   vtype = (fileType == 0) ? PETSCVIEWERASCII : PETSCVIEWERBINARY;
1462d6689ca9SLisandro Dalcin 
1463d6689ca9SLisandro Dalcin   /* Create appropriate viewer and build plex */
1464d6689ca9SLisandro Dalcin   ierr = PetscViewerCreate(comm, &viewer);CHKERRQ(ierr);
1465d6689ca9SLisandro Dalcin   ierr = PetscViewerSetType(viewer, vtype);CHKERRQ(ierr);
1466d6689ca9SLisandro Dalcin   ierr = PetscViewerFileSetMode(viewer, FILE_MODE_READ);CHKERRQ(ierr);
1467d6689ca9SLisandro Dalcin   ierr = PetscViewerFileSetName(viewer, filename);CHKERRQ(ierr);
1468d6689ca9SLisandro Dalcin   ierr = DMPlexCreateGmsh(comm, viewer, interpolate, dm);CHKERRQ(ierr);
1469d6689ca9SLisandro Dalcin   ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1470d6689ca9SLisandro Dalcin   PetscFunctionReturn(0);
1471d6689ca9SLisandro Dalcin }
1472d6689ca9SLisandro Dalcin 
1473331830f3SMatthew G. Knepley /*@
14747d282ae0SMichael Lange   DMPlexCreateGmsh - Create a DMPlex mesh from a Gmsh file viewer
1475331830f3SMatthew G. Knepley 
1476d083f849SBarry Smith   Collective
1477331830f3SMatthew G. Knepley 
1478331830f3SMatthew G. Knepley   Input Parameters:
1479331830f3SMatthew G. Knepley + comm  - The MPI communicator
1480331830f3SMatthew G. Knepley . viewer - The Viewer associated with a Gmsh file
1481331830f3SMatthew G. Knepley - interpolate - Create faces and edges in the mesh
1482331830f3SMatthew G. Knepley 
1483331830f3SMatthew G. Knepley   Output Parameter:
1484331830f3SMatthew G. Knepley . dm  - The DM object representing the mesh
1485331830f3SMatthew G. Knepley 
1486698a79b9SLisandro Dalcin   Note: http://gmsh.info/doc/texinfo/gmsh.html#MSH-file-format
1487331830f3SMatthew G. Knepley 
1488331830f3SMatthew G. Knepley   Level: beginner
1489331830f3SMatthew G. Knepley 
1490331830f3SMatthew G. Knepley .seealso: DMPLEX, DMCreate()
1491331830f3SMatthew G. Knepley @*/
1492331830f3SMatthew G. Knepley PetscErrorCode DMPlexCreateGmsh(MPI_Comm comm, PetscViewer viewer, PetscBool interpolate, DM *dm)
1493331830f3SMatthew G. Knepley {
14940598e1a2SLisandro Dalcin   GmshMesh      *mesh = NULL;
149511c56cb0SLisandro Dalcin   PetscViewer    parentviewer = NULL;
14960598e1a2SLisandro Dalcin   PetscBT        periodicVerts = NULL;
14970598e1a2SLisandro Dalcin   PetscBT        periodicCells = NULL;
1498066ea43fSLisandro Dalcin   DM             cdm;
1499331830f3SMatthew G. Knepley   PetscSection   coordSection;
1500331830f3SMatthew G. Knepley   Vec            coordinates;
1501a45dabc8SMatthew G. Knepley   DMLabel        cellSets = NULL, faceSets = NULL, vertSets = NULL, marker = NULL, *regionSets;
1502066ea43fSLisandro Dalcin   PetscInt       dim = 0, coordDim = -1, order = 0;
15030598e1a2SLisandro Dalcin   PetscInt       numNodes = 0, numElems = 0, numVerts = 0, numCells = 0;
1504066ea43fSLisandro Dalcin   PetscInt       cell, cone[8], e, n, v, d;
1505*81a1af93SMatthew G. Knepley   PetscBool      binary, usemarker = PETSC_FALSE, useregions = PETSC_FALSE, markvertices = PETSC_FALSE;
15060598e1a2SLisandro Dalcin   PetscBool      hybrid = interpolate, periodic = PETSC_TRUE;
1507066ea43fSLisandro Dalcin   PetscBool      highOrder = PETSC_TRUE, highOrderSet, project = PETSC_FALSE;
1508066ea43fSLisandro Dalcin   PetscBool      isSimplex = PETSC_FALSE, isHybrid = PETSC_FALSE, hasTetra = PETSC_FALSE;
15090598e1a2SLisandro Dalcin   PetscMPIInt    rank;
1510331830f3SMatthew G. Knepley   PetscErrorCode ierr;
1511331830f3SMatthew G. Knepley 
1512331830f3SMatthew G. Knepley   PetscFunctionBegin;
1513ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
1514ef12879bSLisandro Dalcin   ierr = PetscObjectOptionsBegin((PetscObject)viewer);CHKERRQ(ierr);
1515ef12879bSLisandro Dalcin   ierr = PetscOptionsHead(PetscOptionsObject,"DMPlex Gmsh options");CHKERRQ(ierr);
15160598e1a2SLisandro Dalcin   ierr = PetscOptionsBool("-dm_plex_gmsh_hybrid", "Generate hybrid cell bounds", "DMPlexCreateGmsh", hybrid, &hybrid, NULL);CHKERRQ(ierr);
1517ef12879bSLisandro Dalcin   ierr = PetscOptionsBool("-dm_plex_gmsh_periodic","Read Gmsh periodic section", "DMPlexCreateGmsh", periodic, &periodic, NULL);CHKERRQ(ierr);
1518066ea43fSLisandro Dalcin   ierr = PetscOptionsBool("-dm_plex_gmsh_highorder","Generate high-order coordinates", "DMPlexCreateGmsh", highOrder, &highOrder, &highOrderSet);CHKERRQ(ierr);
1519066ea43fSLisandro Dalcin   ierr = PetscOptionsBool("-dm_plex_gmsh_project", "Project high-order coordinates to a different space", "DMPlexCreateGmsh", project, &project, NULL);CHKERRQ(ierr);
1520ef12879bSLisandro Dalcin   ierr = PetscOptionsBool("-dm_plex_gmsh_use_marker", "Generate marker label", "DMPlexCreateGmsh", usemarker, &usemarker, NULL);CHKERRQ(ierr);
1521a45dabc8SMatthew G. Knepley   ierr = PetscOptionsBool("-dm_plex_gmsh_use_regions", "Generate labels with region names", "DMPlexCreateGmsh", useregions, &useregions, NULL);CHKERRQ(ierr);
1522*81a1af93SMatthew G. Knepley   ierr = PetscOptionsBool("-dm_plex_gmsh_mark_vertices", "Add vertices to generated labels", "DMPlexCreateGmsh", markvertices, &markvertices, NULL);CHKERRQ(ierr);
15230598e1a2SLisandro Dalcin   ierr = PetscOptionsBoundedInt("-dm_plex_gmsh_spacedim", "Embedding space dimension", "DMPlexCreateGmsh", coordDim, &coordDim, NULL, PETSC_DECIDE);CHKERRQ(ierr);
1524ef12879bSLisandro Dalcin   ierr = PetscOptionsTail();CHKERRQ(ierr);
1525ef12879bSLisandro Dalcin   ierr = PetscOptionsEnd();CHKERRQ(ierr);
15260598e1a2SLisandro Dalcin 
15270598e1a2SLisandro Dalcin   ierr = GmshCellInfoSetUp();CHKERRQ(ierr);
152811c56cb0SLisandro Dalcin 
1529331830f3SMatthew G. Knepley   ierr = DMCreate(comm, dm);CHKERRQ(ierr);
1530331830f3SMatthew G. Knepley   ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr);
15310598e1a2SLisandro Dalcin   ierr = PetscLogEventBegin(DMPLEX_CreateGmsh,*dm,NULL,NULL,NULL);CHKERRQ(ierr);
153211c56cb0SLisandro Dalcin 
153311c56cb0SLisandro Dalcin   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &binary);CHKERRQ(ierr);
153411c56cb0SLisandro Dalcin 
153511c56cb0SLisandro Dalcin   /* Binary viewers read on all ranks, get subviewer to read only in rank 0 */
15363b46f529SLisandro Dalcin   if (binary) {
153711c56cb0SLisandro Dalcin     parentviewer = viewer;
153811c56cb0SLisandro Dalcin     ierr = PetscViewerGetSubViewer(parentviewer, PETSC_COMM_SELF, &viewer);CHKERRQ(ierr);
153911c56cb0SLisandro Dalcin   }
154011c56cb0SLisandro Dalcin 
1541dd400576SPatrick Sanan   if (rank == 0) {
15420598e1a2SLisandro Dalcin     GmshFile  gmsh[1];
1543698a79b9SLisandro Dalcin     char      line[PETSC_MAX_PATH_LEN];
1544698a79b9SLisandro Dalcin     PetscBool match;
1545331830f3SMatthew G. Knepley 
1546580bdb30SBarry Smith     ierr = PetscArrayzero(gmsh,1);CHKERRQ(ierr);
1547698a79b9SLisandro Dalcin     gmsh->viewer = viewer;
1548698a79b9SLisandro Dalcin     gmsh->binary = binary;
1549698a79b9SLisandro Dalcin 
15500598e1a2SLisandro Dalcin     ierr = GmshMeshCreate(&mesh);CHKERRQ(ierr);
15510598e1a2SLisandro Dalcin 
1552698a79b9SLisandro Dalcin     /* Read mesh format */
1553d6689ca9SLisandro Dalcin     ierr = GmshReadSection(gmsh, line);CHKERRQ(ierr);
1554d6689ca9SLisandro Dalcin     ierr = GmshExpect(gmsh, "$MeshFormat", line);CHKERRQ(ierr);
15550598e1a2SLisandro Dalcin     ierr = GmshReadMeshFormat(gmsh);CHKERRQ(ierr);
1556d6689ca9SLisandro Dalcin     ierr = GmshReadEndSection(gmsh, "$EndMeshFormat", line);CHKERRQ(ierr);
155711c56cb0SLisandro Dalcin 
1558dc0ede3bSMatthew G. Knepley     /* OPTIONAL Read physical names */
1559d6689ca9SLisandro Dalcin     ierr = GmshReadSection(gmsh, line);CHKERRQ(ierr);
1560d6689ca9SLisandro Dalcin     ierr = GmshMatch(gmsh, "$PhysicalNames", line, &match);CHKERRQ(ierr);
1561dc0ede3bSMatthew G. Knepley     if (match) {
15620598e1a2SLisandro Dalcin       ierr = GmshExpect(gmsh, "$PhysicalNames", line);CHKERRQ(ierr);
1563a45dabc8SMatthew G. Knepley       ierr = GmshReadPhysicalNames(gmsh, mesh);CHKERRQ(ierr);
1564d6689ca9SLisandro Dalcin       ierr = GmshReadEndSection(gmsh, "$EndPhysicalNames", line);CHKERRQ(ierr);
1565698a79b9SLisandro Dalcin       /* Initial read for entity section */
1566d6689ca9SLisandro Dalcin       ierr = GmshReadSection(gmsh, line);CHKERRQ(ierr);
1567dc0ede3bSMatthew G. Knepley     }
156811c56cb0SLisandro Dalcin 
1569de78e4feSLisandro Dalcin     /* Read entities */
1570698a79b9SLisandro Dalcin     if (gmsh->fileFormat >= 40) {
1571d6689ca9SLisandro Dalcin       ierr = GmshExpect(gmsh, "$Entities", line);CHKERRQ(ierr);
15720598e1a2SLisandro Dalcin       ierr = GmshReadEntities(gmsh, mesh);CHKERRQ(ierr);
1573d6689ca9SLisandro Dalcin       ierr = GmshReadEndSection(gmsh, "$EndEntities", line);CHKERRQ(ierr);
1574698a79b9SLisandro Dalcin       /* Initial read for nodes section */
1575d6689ca9SLisandro Dalcin       ierr = GmshReadSection(gmsh, line);CHKERRQ(ierr);
1576de78e4feSLisandro Dalcin     }
1577de78e4feSLisandro Dalcin 
1578698a79b9SLisandro Dalcin     /* Read nodes */
1579d6689ca9SLisandro Dalcin     ierr = GmshExpect(gmsh, "$Nodes", line);CHKERRQ(ierr);
15800598e1a2SLisandro Dalcin     ierr = GmshReadNodes(gmsh, mesh);CHKERRQ(ierr);
1581d6689ca9SLisandro Dalcin     ierr = GmshReadEndSection(gmsh, "$EndNodes", line);CHKERRQ(ierr);
158211c56cb0SLisandro Dalcin 
1583698a79b9SLisandro Dalcin     /* Read elements */
1584feb237baSPierre Jolivet     ierr = GmshReadSection(gmsh, line);CHKERRQ(ierr);
1585d6689ca9SLisandro Dalcin     ierr = GmshExpect(gmsh, "$Elements", line);CHKERRQ(ierr);
15860598e1a2SLisandro Dalcin     ierr = GmshReadElements(gmsh, mesh);CHKERRQ(ierr);
1587d6689ca9SLisandro Dalcin     ierr = GmshReadEndSection(gmsh, "$EndElements", line);CHKERRQ(ierr);
1588de78e4feSLisandro Dalcin 
15890598e1a2SLisandro Dalcin     /* Read periodic section (OPTIONAL) */
1590698a79b9SLisandro Dalcin     if (periodic) {
1591ef12879bSLisandro Dalcin       ierr = GmshReadSection(gmsh, line);CHKERRQ(ierr);
1592ef12879bSLisandro Dalcin       ierr = GmshMatch(gmsh, "$Periodic", line, &periodic);CHKERRQ(ierr);
1593ef12879bSLisandro Dalcin     }
1594ef12879bSLisandro Dalcin     if (periodic) {
1595d6689ca9SLisandro Dalcin       ierr = GmshExpect(gmsh, "$Periodic", line);CHKERRQ(ierr);
15960598e1a2SLisandro Dalcin       ierr = GmshReadPeriodic(gmsh, mesh);CHKERRQ(ierr);
1597d6689ca9SLisandro Dalcin       ierr = GmshReadEndSection(gmsh, "$EndPeriodic", line);CHKERRQ(ierr);
1598698a79b9SLisandro Dalcin     }
1599698a79b9SLisandro Dalcin 
1600698a79b9SLisandro Dalcin     ierr = PetscFree(gmsh->wbuf);CHKERRQ(ierr);
1601698a79b9SLisandro Dalcin     ierr = PetscFree(gmsh->sbuf);CHKERRQ(ierr);
16020598e1a2SLisandro Dalcin     ierr = PetscFree(gmsh->nbuf);CHKERRQ(ierr);
16030598e1a2SLisandro Dalcin 
16040598e1a2SLisandro Dalcin     dim       = mesh->dim;
1605066ea43fSLisandro Dalcin     order     = mesh->order;
16060598e1a2SLisandro Dalcin     numNodes  = mesh->numNodes;
16070598e1a2SLisandro Dalcin     numElems  = mesh->numElems;
16080598e1a2SLisandro Dalcin     numVerts  = mesh->numVerts;
16090598e1a2SLisandro Dalcin     numCells  = mesh->numCells;
1610066ea43fSLisandro Dalcin 
1611066ea43fSLisandro Dalcin     {
1612066ea43fSLisandro Dalcin       GmshElement *elemA = mesh->numCells > 0 ? mesh->elements : NULL;
1613066ea43fSLisandro Dalcin       GmshElement *elemB = elemA ? elemA + mesh->numCells - 1  : NULL;
1614066ea43fSLisandro Dalcin       int ptA = elemA ? GmshCellMap[elemA->cellType].polytope : -1;
1615066ea43fSLisandro Dalcin       int ptB = elemB ? GmshCellMap[elemB->cellType].polytope : -1;
1616066ea43fSLisandro Dalcin       isSimplex = (ptA == GMSH_QUA || ptA == GMSH_HEX) ? PETSC_FALSE : PETSC_TRUE;
1617066ea43fSLisandro Dalcin       isHybrid  = (ptA == ptB) ? PETSC_FALSE : PETSC_TRUE;
1618066ea43fSLisandro Dalcin       hasTetra  = (ptA == GMSH_TET) ? PETSC_TRUE : PETSC_FALSE;
1619066ea43fSLisandro Dalcin     }
1620698a79b9SLisandro Dalcin   }
1621698a79b9SLisandro Dalcin 
1622698a79b9SLisandro Dalcin   if (parentviewer) {
1623698a79b9SLisandro Dalcin     ierr = PetscViewerRestoreSubViewer(parentviewer, PETSC_COMM_SELF, &viewer);CHKERRQ(ierr);
1624698a79b9SLisandro Dalcin   }
1625698a79b9SLisandro Dalcin 
1626066ea43fSLisandro Dalcin   {
1627066ea43fSLisandro Dalcin     int buf[6];
1628698a79b9SLisandro Dalcin 
1629066ea43fSLisandro Dalcin     buf[0] = (int)dim;
1630066ea43fSLisandro Dalcin     buf[1] = (int)order;
1631066ea43fSLisandro Dalcin     buf[2] = periodic;
1632066ea43fSLisandro Dalcin     buf[3] = isSimplex;
1633066ea43fSLisandro Dalcin     buf[4] = isHybrid;
1634066ea43fSLisandro Dalcin     buf[5] = hasTetra;
1635066ea43fSLisandro Dalcin 
1636ffc4695bSBarry Smith     ierr = MPI_Bcast(buf, 6, MPI_INT, 0, comm);CHKERRMPI(ierr);
1637066ea43fSLisandro Dalcin 
1638066ea43fSLisandro Dalcin     dim       = buf[0];
1639066ea43fSLisandro Dalcin     order     = buf[1];
1640066ea43fSLisandro Dalcin     periodic  = buf[2] ? PETSC_TRUE : PETSC_FALSE;
1641066ea43fSLisandro Dalcin     isSimplex = buf[3] ? PETSC_TRUE : PETSC_FALSE;
1642066ea43fSLisandro Dalcin     isHybrid  = buf[4] ? PETSC_TRUE : PETSC_FALSE;
1643066ea43fSLisandro Dalcin     hasTetra  = buf[5] ? PETSC_TRUE : PETSC_FALSE;
1644dea2a3c7SStefano Zampini   }
1645dea2a3c7SStefano Zampini 
1646066ea43fSLisandro Dalcin   if (!highOrderSet) highOrder = (order > 1) ? PETSC_TRUE : PETSC_FALSE;
16472c71b3e2SJacob Faibussowitsch   PetscCheckFalse(highOrder && isHybrid,comm, PETSC_ERR_SUP, "No support for discretization on hybrid meshes yet");
1648066ea43fSLisandro Dalcin 
16490598e1a2SLisandro Dalcin   /* We do not want this label automatically computed, instead we fill it here */
16500598e1a2SLisandro Dalcin   ierr = DMCreateLabel(*dm, "celltype");CHKERRQ(ierr);
165111c56cb0SLisandro Dalcin 
1652a4bb7517SMichael Lange   /* Allocate the cell-vertex mesh */
16530598e1a2SLisandro Dalcin   ierr = DMPlexSetChart(*dm, 0, numCells+numVerts);CHKERRQ(ierr);
16540598e1a2SLisandro Dalcin   for (cell = 0; cell < numCells; ++cell) {
16550598e1a2SLisandro Dalcin     GmshElement *elem = mesh->elements + cell;
16560598e1a2SLisandro Dalcin     DMPolytopeType ctype = DMPolytopeTypeFromGmsh(elem->cellType);
16570598e1a2SLisandro Dalcin     if (hybrid && hasTetra && ctype == DM_POLYTOPE_TRI_PRISM) ctype = DM_POLYTOPE_TRI_PRISM_TENSOR;
16580598e1a2SLisandro Dalcin     ierr = DMPlexSetConeSize(*dm, cell, elem->numVerts);CHKERRQ(ierr);
16590598e1a2SLisandro Dalcin     ierr = DMPlexSetCellType(*dm, cell, ctype);CHKERRQ(ierr);
1660db397164SMichael Lange   }
16610598e1a2SLisandro Dalcin   for (v = numCells; v < numCells+numVerts; ++v) {
166296ca5757SLisandro Dalcin     ierr = DMPlexSetCellType(*dm, v, DM_POLYTOPE_POINT);CHKERRQ(ierr);
166396ca5757SLisandro Dalcin   }
1664331830f3SMatthew G. Knepley   ierr = DMSetUp(*dm);CHKERRQ(ierr);
166596ca5757SLisandro Dalcin 
1666a4bb7517SMichael Lange   /* Add cell-vertex connections */
16670598e1a2SLisandro Dalcin   for (cell = 0; cell < numCells; ++cell) {
16680598e1a2SLisandro Dalcin     GmshElement *elem = mesh->elements + cell;
16690598e1a2SLisandro Dalcin     for (v = 0; v < elem->numVerts; ++v) {
16700598e1a2SLisandro Dalcin       const PetscInt nn = elem->nodes[v];
16710598e1a2SLisandro Dalcin       const PetscInt vv = mesh->vertexMap[nn];
16720598e1a2SLisandro Dalcin       cone[v] = numCells + vv;
1673db397164SMichael Lange     }
16740598e1a2SLisandro Dalcin     ierr = DMPlexReorderCell(*dm, cell, cone);CHKERRQ(ierr);
16750598e1a2SLisandro Dalcin     ierr = DMPlexSetCone(*dm, cell, cone);CHKERRQ(ierr);
1676a4bb7517SMichael Lange   }
167796ca5757SLisandro Dalcin 
1678c73cfb54SMatthew G. Knepley   ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr);
1679331830f3SMatthew G. Knepley   ierr = DMPlexSymmetrize(*dm);CHKERRQ(ierr);
1680331830f3SMatthew G. Knepley   ierr = DMPlexStratify(*dm);CHKERRQ(ierr);
1681331830f3SMatthew G. Knepley   if (interpolate) {
16825fd9971aSMatthew G. Knepley     DM idm;
1683331830f3SMatthew G. Knepley 
1684331830f3SMatthew G. Knepley     ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr);
1685331830f3SMatthew G. Knepley     ierr = DMDestroy(dm);CHKERRQ(ierr);
1686331830f3SMatthew G. Knepley     *dm  = idm;
1687331830f3SMatthew G. Knepley   }
1688917266a4SLisandro Dalcin 
1689*81a1af93SMatthew G. Knepley   /* Create the label "marker" over the whole boundary */
16902c71b3e2SJacob Faibussowitsch   PetscCheckFalse(usemarker && !interpolate && dim > 1,comm,PETSC_ERR_SUP,"Cannot create marker label without interpolation");
1691dd400576SPatrick Sanan   if (rank == 0 && usemarker) {
1692d3f73514SStefano Zampini     PetscInt f, fStart, fEnd;
1693d3f73514SStefano Zampini 
1694d3f73514SStefano Zampini     ierr = DMCreateLabel(*dm, "marker");CHKERRQ(ierr);
1695d3f73514SStefano Zampini     ierr = DMPlexGetHeightStratum(*dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
1696d3f73514SStefano Zampini     for (f = fStart; f < fEnd; ++f) {
1697d3f73514SStefano Zampini       PetscInt suppSize;
1698d3f73514SStefano Zampini 
1699d3f73514SStefano Zampini       ierr = DMPlexGetSupportSize(*dm, f, &suppSize);CHKERRQ(ierr);
1700d3f73514SStefano Zampini       if (suppSize == 1) {
1701d3f73514SStefano Zampini         PetscInt *cone = NULL, coneSize, p;
1702d3f73514SStefano Zampini 
1703d3f73514SStefano Zampini         ierr = DMPlexGetTransitiveClosure(*dm, f, PETSC_TRUE, &coneSize, &cone);CHKERRQ(ierr);
1704d3f73514SStefano Zampini         for (p = 0; p < coneSize; p += 2) {
17057dd454faSLisandro Dalcin           ierr = DMSetLabelValue_Fast(*dm, &marker, "marker", cone[p], 1);CHKERRQ(ierr);
1706d3f73514SStefano Zampini         }
1707d3f73514SStefano Zampini         ierr = DMPlexRestoreTransitiveClosure(*dm, f, PETSC_TRUE, &coneSize, &cone);CHKERRQ(ierr);
1708d3f73514SStefano Zampini       }
1709d3f73514SStefano Zampini     }
1710d3f73514SStefano Zampini   }
171116ad7e67SMichael Lange 
1712dd400576SPatrick Sanan   if (rank == 0) {
1713a45dabc8SMatthew G. Knepley     const PetscInt Nr = useregions ? mesh->numRegions : 0;
171411c56cb0SLisandro Dalcin     PetscInt       vStart, vEnd;
1715d1a54cefSMatthew G. Knepley 
1716a45dabc8SMatthew G. Knepley     ierr = PetscCalloc1(Nr, &regionSets);CHKERRQ(ierr);
171716ad7e67SMichael Lange     ierr = DMPlexGetDepthStratum(*dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
17180598e1a2SLisandro Dalcin     for (cell = 0, e = 0; e < numElems; ++e) {
17190598e1a2SLisandro Dalcin       GmshElement *elem = mesh->elements + e;
17206e1dd89aSLawrence Mitchell 
17216e1dd89aSLawrence Mitchell       /* Create cell sets */
17220598e1a2SLisandro Dalcin       if (elem->dim == dim && dim > 0) {
17230598e1a2SLisandro Dalcin         if (elem->numTags > 0) {
1724a45dabc8SMatthew G. Knepley           const PetscInt tag = elem->tags[0];
1725a45dabc8SMatthew G. Knepley           PetscInt       r;
1726a45dabc8SMatthew G. Knepley 
1727*81a1af93SMatthew G. Knepley           if (!Nr) {ierr = DMSetLabelValue_Fast(*dm, &cellSets, "Cell Sets", cell, tag);CHKERRQ(ierr);}
1728a45dabc8SMatthew G. Knepley           for (r = 0; r < Nr; ++r) {
1729a45dabc8SMatthew G. Knepley             if (mesh->regionTags[r] == tag) {ierr = DMSetLabelValue_Fast(*dm, &regionSets[r], mesh->regionNames[r], cell, tag);CHKERRQ(ierr);}
1730a45dabc8SMatthew G. Knepley           }
17316e1dd89aSLawrence Mitchell         }
1732917266a4SLisandro Dalcin         cell++;
17336e1dd89aSLawrence Mitchell       }
17340c070f12SSander Arens 
17350598e1a2SLisandro Dalcin       /* Create face sets */
17360598e1a2SLisandro Dalcin       if (interpolate && elem->dim == dim-1) {
17370598e1a2SLisandro Dalcin         PetscInt        joinSize;
17380598e1a2SLisandro Dalcin         const PetscInt *join = NULL;
1739a45dabc8SMatthew G. Knepley         const PetscInt  tag = elem->tags[0];
1740a45dabc8SMatthew G. Knepley         PetscInt        r;
1741a45dabc8SMatthew G. Knepley 
17420598e1a2SLisandro Dalcin         /* Find the relevant facet with vertex joins */
17430598e1a2SLisandro Dalcin         for (v = 0; v < elem->numVerts; ++v) {
17440598e1a2SLisandro Dalcin           const PetscInt nn = elem->nodes[v];
17450598e1a2SLisandro Dalcin           const PetscInt vv = mesh->vertexMap[nn];
17460598e1a2SLisandro Dalcin           cone[v] = vStart + vv;
17470598e1a2SLisandro Dalcin         }
17480598e1a2SLisandro Dalcin         ierr = DMPlexGetFullJoin(*dm, elem->numVerts, cone, &joinSize, &join);CHKERRQ(ierr);
17492c71b3e2SJacob Faibussowitsch         PetscCheckFalse(joinSize != 1,PETSC_COMM_SELF, PETSC_ERR_SUP, "Could not determine Plex facet for Gmsh element %D (Plex cell %D)", elem->id, e);
1750*81a1af93SMatthew G. Knepley         if (!Nr) {ierr = DMSetLabelValue_Fast(*dm, &faceSets, "Face Sets", join[0], tag);CHKERRQ(ierr);}
1751a45dabc8SMatthew G. Knepley         for (r = 0; r < Nr; ++r) {
1752a45dabc8SMatthew G. Knepley           if (mesh->regionTags[r] == tag) {ierr = DMSetLabelValue_Fast(*dm, &regionSets[r], mesh->regionNames[r], join[0], tag);CHKERRQ(ierr);}
1753a45dabc8SMatthew G. Knepley         }
17540598e1a2SLisandro Dalcin         ierr = DMPlexRestoreJoin(*dm, elem->numVerts, cone, &joinSize, &join);CHKERRQ(ierr);
17550598e1a2SLisandro Dalcin       }
17560598e1a2SLisandro Dalcin 
17570c070f12SSander Arens       /* Create vertex sets */
17580598e1a2SLisandro Dalcin       if (elem->dim == 0) {
17590598e1a2SLisandro Dalcin         if (elem->numTags > 0) {
17600598e1a2SLisandro Dalcin           const PetscInt nn = elem->nodes[0];
17610598e1a2SLisandro Dalcin           const PetscInt vv = mesh->vertexMap[nn];
1762a45dabc8SMatthew G. Knepley           const PetscInt tag = elem->tags[0];
1763a45dabc8SMatthew G. Knepley           PetscInt       r;
1764a45dabc8SMatthew G. Knepley 
1765*81a1af93SMatthew G. Knepley           if (!Nr) {ierr = DMSetLabelValue_Fast(*dm, &vertSets, "Vertex Sets", vStart + vv, tag);CHKERRQ(ierr);}
1766*81a1af93SMatthew G. Knepley           for (r = 0; r < Nr; ++r) {
1767*81a1af93SMatthew G. Knepley             if (mesh->regionTags[r] == tag) {ierr = DMSetLabelValue_Fast(*dm, &regionSets[r], mesh->regionNames[r], vStart + vv, tag);CHKERRQ(ierr);}
1768*81a1af93SMatthew G. Knepley           }
1769*81a1af93SMatthew G. Knepley         }
1770*81a1af93SMatthew G. Knepley       }
1771*81a1af93SMatthew G. Knepley     }
1772*81a1af93SMatthew G. Knepley     if (markvertices) {
1773*81a1af93SMatthew G. Knepley       for (v = 0; v < numNodes; ++v) {
1774*81a1af93SMatthew G. Knepley         const PetscInt vv  = mesh->vertexMap[v];
1775*81a1af93SMatthew G. Knepley         const PetscInt tag = mesh->nodelist->tag[v];
1776*81a1af93SMatthew G. Knepley         PetscInt       r;
1777*81a1af93SMatthew G. Knepley 
1778*81a1af93SMatthew G. Knepley         if (tag != -1) {
1779*81a1af93SMatthew G. Knepley           if (!Nr) {ierr = DMSetLabelValue_Fast(*dm, &vertSets, "Vertex Sets", vStart + vv, tag);CHKERRQ(ierr);}
1780a45dabc8SMatthew G. Knepley           for (r = 0; r < Nr; ++r) {
1781a45dabc8SMatthew G. Knepley             if (mesh->regionTags[r] == tag) {ierr = DMSetLabelValue_Fast(*dm, &regionSets[r], mesh->regionNames[r], vStart + vv, tag);CHKERRQ(ierr);}
17820598e1a2SLisandro Dalcin           }
17830598e1a2SLisandro Dalcin         }
17840598e1a2SLisandro Dalcin       }
17850598e1a2SLisandro Dalcin     }
1786a45dabc8SMatthew G. Knepley     ierr = PetscFree(regionSets);CHKERRQ(ierr);
1787a45dabc8SMatthew G. Knepley   }
17880598e1a2SLisandro Dalcin 
17897dd454faSLisandro Dalcin   { /* Create Cell/Face/Vertex Sets labels at all processes */
17907dd454faSLisandro Dalcin     enum {n = 4};
17917dd454faSLisandro Dalcin     PetscBool flag[n];
17927dd454faSLisandro Dalcin 
17937dd454faSLisandro Dalcin     flag[0] = cellSets ? PETSC_TRUE : PETSC_FALSE;
17947dd454faSLisandro Dalcin     flag[1] = faceSets ? PETSC_TRUE : PETSC_FALSE;
17957dd454faSLisandro Dalcin     flag[2] = vertSets ? PETSC_TRUE : PETSC_FALSE;
17967dd454faSLisandro Dalcin     flag[3] = marker   ? PETSC_TRUE : PETSC_FALSE;
17977dd454faSLisandro Dalcin     ierr = MPI_Bcast(flag, n, MPIU_BOOL, 0, comm);CHKERRMPI(ierr);
17987dd454faSLisandro Dalcin     if (flag[0]) {ierr = DMCreateLabel(*dm, "Cell Sets");CHKERRQ(ierr);}
17997dd454faSLisandro Dalcin     if (flag[1]) {ierr = DMCreateLabel(*dm, "Face Sets");CHKERRQ(ierr);}
18007dd454faSLisandro Dalcin     if (flag[2]) {ierr = DMCreateLabel(*dm, "Vertex Sets");CHKERRQ(ierr);}
18017dd454faSLisandro Dalcin     if (flag[3]) {ierr = DMCreateLabel(*dm, "marker");CHKERRQ(ierr);}
18027dd454faSLisandro Dalcin   }
18037dd454faSLisandro Dalcin 
18040598e1a2SLisandro Dalcin   if (periodic) {
18050598e1a2SLisandro Dalcin     ierr = PetscBTCreate(numVerts, &periodicVerts);CHKERRQ(ierr);
18060598e1a2SLisandro Dalcin     for (n = 0; n < numNodes; ++n) {
18070598e1a2SLisandro Dalcin       if (mesh->vertexMap[n] >= 0) {
18080598e1a2SLisandro Dalcin         if (PetscUnlikely(mesh->periodMap[n] != n)) {
18090598e1a2SLisandro Dalcin           PetscInt m = mesh->periodMap[n];
18100598e1a2SLisandro Dalcin           ierr = PetscBTSet(periodicVerts, mesh->vertexMap[n]);CHKERRQ(ierr);
18110598e1a2SLisandro Dalcin           ierr = PetscBTSet(periodicVerts, mesh->vertexMap[m]);CHKERRQ(ierr);
18120598e1a2SLisandro Dalcin         }
18130598e1a2SLisandro Dalcin       }
18140598e1a2SLisandro Dalcin     }
18150598e1a2SLisandro Dalcin     ierr = PetscBTCreate(numCells, &periodicCells);CHKERRQ(ierr);
18160598e1a2SLisandro Dalcin     for (cell = 0; cell < numCells; ++cell) {
18170598e1a2SLisandro Dalcin       GmshElement *elem = mesh->elements + cell;
18180598e1a2SLisandro Dalcin       for (v = 0; v < elem->numVerts; ++v) {
18190598e1a2SLisandro Dalcin         PetscInt nn = elem->nodes[v];
18200598e1a2SLisandro Dalcin         PetscInt vv = mesh->vertexMap[nn];
18210598e1a2SLisandro Dalcin         if (PetscUnlikely(PetscBTLookup(periodicVerts, vv))) {
18220598e1a2SLisandro Dalcin           ierr = PetscBTSet(periodicCells, cell);CHKERRQ(ierr); break;
18230c070f12SSander Arens         }
18240c070f12SSander Arens       }
18250c070f12SSander Arens     }
182616ad7e67SMichael Lange   }
182716ad7e67SMichael Lange 
1828066ea43fSLisandro Dalcin   /* Setup coordinate DM */
18290598e1a2SLisandro Dalcin   if (coordDim < 0) coordDim = dim;
18300598e1a2SLisandro Dalcin   ierr = DMSetCoordinateDim(*dm, coordDim);CHKERRQ(ierr);
1831066ea43fSLisandro Dalcin   ierr = DMGetCoordinateDM(*dm, &cdm);CHKERRQ(ierr);
1832066ea43fSLisandro Dalcin   if (highOrder) {
1833066ea43fSLisandro Dalcin     PetscFE         fe;
1834066ea43fSLisandro Dalcin     PetscBool       continuity = periodic ? PETSC_FALSE : PETSC_TRUE;
1835066ea43fSLisandro Dalcin     PetscDTNodeType nodeType   = PETSCDTNODES_EQUISPACED;
1836066ea43fSLisandro Dalcin 
1837066ea43fSLisandro Dalcin     if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */
1838066ea43fSLisandro Dalcin 
1839066ea43fSLisandro Dalcin     ierr = GmshCreateFE(comm, NULL, isSimplex, continuity, nodeType, dim, coordDim, order, &fe);CHKERRQ(ierr);
1840066ea43fSLisandro Dalcin     ierr = PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_fe_view");CHKERRQ(ierr);
1841066ea43fSLisandro Dalcin     ierr = DMSetField(cdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr);
1842066ea43fSLisandro Dalcin     ierr = PetscFEDestroy(&fe);CHKERRQ(ierr);
1843066ea43fSLisandro Dalcin     ierr = DMCreateDS(cdm);CHKERRQ(ierr);
1844066ea43fSLisandro Dalcin   }
1845066ea43fSLisandro Dalcin 
1846066ea43fSLisandro Dalcin   /* Create coordinates */
1847066ea43fSLisandro Dalcin   if (highOrder) {
1848066ea43fSLisandro Dalcin 
1849066ea43fSLisandro Dalcin     PetscInt     maxDof = GmshNumNodes_HEX(order)*coordDim;
1850066ea43fSLisandro Dalcin     double       *coords = mesh ? mesh->nodelist->xyz : NULL;
1851066ea43fSLisandro Dalcin     PetscSection section;
1852066ea43fSLisandro Dalcin     PetscScalar  *cellCoords;
1853066ea43fSLisandro Dalcin 
1854066ea43fSLisandro Dalcin     ierr = DMSetLocalSection(cdm, NULL);CHKERRQ(ierr);
1855066ea43fSLisandro Dalcin     ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr);
1856066ea43fSLisandro Dalcin     ierr = PetscSectionClone(coordSection, &section);CHKERRQ(ierr);
1857066ea43fSLisandro Dalcin     ierr = DMPlexSetClosurePermutationTensor(cdm, 0, section);CHKERRQ(ierr); /* XXX Implement DMPlexSetClosurePermutationLexicographic() */
1858066ea43fSLisandro Dalcin 
1859066ea43fSLisandro Dalcin     ierr = DMCreateLocalVector(cdm, &coordinates);CHKERRQ(ierr);
1860066ea43fSLisandro Dalcin     ierr = PetscMalloc1(maxDof, &cellCoords);CHKERRQ(ierr);
1861066ea43fSLisandro Dalcin     for (cell = 0; cell < numCells; ++cell) {
1862066ea43fSLisandro Dalcin       GmshElement *elem = mesh->elements + cell;
1863066ea43fSLisandro Dalcin       const int *lexorder = GmshCellMap[elem->cellType].lexorder();
1864b9bf55e5SMatthew G. Knepley       int s = 0;
1865066ea43fSLisandro Dalcin       for (n = 0; n < elem->numNodes; ++n) {
1866b9bf55e5SMatthew G. Knepley         while (lexorder[n+s] < 0) ++s;
1867b9bf55e5SMatthew G. Knepley         const PetscInt node = elem->nodes[lexorder[n+s]];
1868b9bf55e5SMatthew G. Knepley         for (d = 0; d < coordDim; ++d) cellCoords[(n+s)*coordDim+d] = (PetscReal) coords[node*3+d];
1869b9bf55e5SMatthew G. Knepley       }
1870b9bf55e5SMatthew G. Knepley       if (s) {
1871b9bf55e5SMatthew G. Knepley         /* For the coordinate mapping we weight vertices by -1/4 and edges by 1/2, which we get from Q_2 interpolation */
1872b9bf55e5SMatthew G. Knepley         PetscReal quaCenterWeights[9]  = {-0.25, 0.5, -0.25, 0.5, 0.0, 0.5, -0.25, 0.5, -0.25};
1873b9bf55e5SMatthew G. Knepley         /* For the coordinate mapping we weight vertices by -1/4 and edges by 1/2, which we get from Q_2 interpolation */
1874b9bf55e5SMatthew G. Knepley         PetscReal hexBottomWeights[27] = {-0.25, 0.5,  -0.25, 0.5,  0.0, 0.5,  -0.25, 0.5,  -0.25,
1875b9bf55e5SMatthew G. Knepley                                            0.0,  0.0,   0.0,  0.0,  0.0, 0.0,   0.0,  0.0,   0.0,
1876b9bf55e5SMatthew G. Knepley                                            0.0,  0.0,   0.0,  0.0,  0.0, 0.0,   0.0,  0.0,   0.0};
1877b9bf55e5SMatthew G. Knepley         PetscReal hexFrontWeights[27]  = {-0.25, 0.5,  -0.25, 0.0,  0.0, 0.0,   0.0,  0.0,   0.0,
1878b9bf55e5SMatthew G. Knepley                                            0.5,  0.0,   0.5,  0.0,  0.0, 0.0,   0.0,  0.0,   0.0,
1879b9bf55e5SMatthew G. Knepley                                           -0.25, 0.5,  -0.25, 0.0,  0.0, 0.0,   0.0,  0.0,   0.0};
1880b9bf55e5SMatthew G. Knepley         PetscReal hexLeftWeights[27]   = {-0.25, 0.0,   0.0,  0.5,  0.0, 0.0,  -0.25, 0.0,   0.0,
1881b9bf55e5SMatthew G. Knepley                                            0.5,  0.0,   0.0,  0.0,  0.0, 0.0,   0.5,  0.0,   0.0,
1882b9bf55e5SMatthew G. Knepley                                           -0.25, 0.0,   0.0,  0.5,  0.0, 0.0,  -0.25, 0.0,   0.0};
1883b9bf55e5SMatthew G. Knepley         PetscReal hexRightWeights[27]  = { 0.0,  0.0,  -0.25, 0.0,  0.0, 0.5,   0.0,  0.0,  -0.25,
1884b9bf55e5SMatthew G. Knepley                                            0.0,  0.0,   0.5,  0.0,  0.0, 0.0,   0.0,  0.0,   0.5,
1885b9bf55e5SMatthew G. Knepley                                            0.0,  0.0,  -0.25, 0.0,  0.0, 0.5,   0.0,  0.0,  -0.25};
1886b9bf55e5SMatthew G. Knepley         PetscReal hexBackWeights[27]   = { 0.0,  0.0,   0.0,  0.0,  0.0, 0.0,  -0.25, 0.5,  -0.25,
1887b9bf55e5SMatthew G. Knepley                                            0.0,  0.0,   0.0,  0.0,  0.0, 0.0,   0.5,  0.0,   0.5,
1888b9bf55e5SMatthew G. Knepley                                            0.0,  0.0,   0.0,  0.0,  0.0, 0.0,  -0.25, 0.5,  -0.25};
1889b9bf55e5SMatthew G. Knepley         PetscReal hexTopWeights[27]    = { 0.0,  0.0,   0.0,  0.0,  0.0, 0.0,   0.0,  0.0,   0.0,
1890b9bf55e5SMatthew G. Knepley                                            0.0,  0.0,   0.0,  0.0,  0.0, 0.0,   0.0,  0.0,   0.0,
1891b9bf55e5SMatthew G. Knepley                                           -0.25, 0.5,  -0.25, 0.5,  0.0, 0.5,  -0.25, 0.5,  -0.25};
1892b9bf55e5SMatthew G. Knepley         PetscReal hexCenterWeights[27] = {-0.25, 0.25, -0.25, 0.25, 0.0, 0.25, -0.25, 0.25, -0.25,
1893b9bf55e5SMatthew G. Knepley                                            0.25, 0.0,   0.25, 0.0,  0.0, 0.0,   0.25, 0.0,   0.25,
1894b9bf55e5SMatthew G. Knepley                                           -0.25, 0.25, -0.25, 0.25, 0.0, 0.25, -0.25, 0.25, -0.25};
1895b9bf55e5SMatthew G. Knepley         PetscReal  *sdWeights2[9]      = {NULL, NULL, NULL, NULL, quaCenterWeights, NULL, NULL, NULL, NULL};
1896b9bf55e5SMatthew G. Knepley         PetscReal  *sdWeights3[27]     = {NULL, NULL, NULL, NULL, hexBottomWeights, NULL, NULL, NULL, NULL,
1897b9bf55e5SMatthew G. Knepley                                           NULL, hexFrontWeights, NULL, hexLeftWeights, hexCenterWeights, hexRightWeights, NULL, hexBackWeights, NULL,
1898b9bf55e5SMatthew G. Knepley                                           NULL, NULL, NULL, NULL, hexTopWeights,    NULL, NULL, NULL, NULL};
1899b9bf55e5SMatthew G. Knepley         PetscReal **sdWeights[4]       = {NULL, NULL, sdWeights2, sdWeights3};
1900b9bf55e5SMatthew G. Knepley 
1901b9bf55e5SMatthew G. Knepley         /* Missing entries in serendipity cell, only works for 8-node quad and 20-node hex */
1902b9bf55e5SMatthew G. Knepley         for (n = 0; n < elem->numNodes+s; ++n) {
1903b9bf55e5SMatthew G. Knepley           if (lexorder[n] >= 0) continue;
1904b9bf55e5SMatthew G. Knepley           for (d = 0; d < coordDim; ++d) cellCoords[n*coordDim+d] = 0.0;
1905b9bf55e5SMatthew G. Knepley           for (int bn = 0; bn < elem->numNodes+s; ++bn) {
1906b9bf55e5SMatthew G. Knepley             if (lexorder[bn] < 0) continue;
1907b9bf55e5SMatthew G. Knepley             const PetscReal *weights = sdWeights[coordDim][n];
1908b9bf55e5SMatthew G. Knepley             const PetscInt   bnode   = elem->nodes[lexorder[bn]];
1909b9bf55e5SMatthew G. Knepley             for (d = 0; d < coordDim; ++d) cellCoords[n*coordDim+d] += weights[bn] * (PetscReal) coords[bnode*3+d];
1910b9bf55e5SMatthew G. Knepley           }
1911b9bf55e5SMatthew G. Knepley         }
1912066ea43fSLisandro Dalcin       }
1913066ea43fSLisandro Dalcin       ierr = DMPlexVecSetClosure(cdm, section, coordinates, cell, cellCoords, INSERT_VALUES);CHKERRQ(ierr);
1914066ea43fSLisandro Dalcin     }
1915066ea43fSLisandro Dalcin     ierr = PetscSectionDestroy(&section);CHKERRQ(ierr);
1916066ea43fSLisandro Dalcin     ierr = PetscFree(cellCoords);CHKERRQ(ierr);
1917066ea43fSLisandro Dalcin 
1918066ea43fSLisandro Dalcin   } else {
1919066ea43fSLisandro Dalcin 
1920066ea43fSLisandro Dalcin     PetscInt    *nodeMap;
1921066ea43fSLisandro Dalcin     double      *coords = mesh ? mesh->nodelist->xyz : NULL;
1922066ea43fSLisandro Dalcin     PetscScalar *pointCoords;
1923066ea43fSLisandro Dalcin 
1924066ea43fSLisandro Dalcin     ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr);
1925331830f3SMatthew G. Knepley     ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr);
19260598e1a2SLisandro Dalcin     ierr = PetscSectionSetFieldComponents(coordSection, 0, coordDim);CHKERRQ(ierr);
19270598e1a2SLisandro Dalcin     if (periodic) { /* we need to localize coordinates on cells */
19280598e1a2SLisandro Dalcin       ierr = PetscSectionSetChart(coordSection, 0, numCells+numVerts);CHKERRQ(ierr);
1929f45c9589SStefano Zampini     } else {
19300598e1a2SLisandro Dalcin       ierr = PetscSectionSetChart(coordSection, numCells, numCells+numVerts);CHKERRQ(ierr);
1931f45c9589SStefano Zampini     }
19320598e1a2SLisandro Dalcin     if (periodic) {
19330598e1a2SLisandro Dalcin       for (cell = 0; cell < numCells; ++cell) {
19340598e1a2SLisandro Dalcin         if (PetscUnlikely(PetscBTLookup(periodicCells, cell))) {
19350598e1a2SLisandro Dalcin           GmshElement *elem = mesh->elements + cell;
19360598e1a2SLisandro Dalcin           PetscInt dof = elem->numVerts * coordDim;
19370598e1a2SLisandro Dalcin           ierr = PetscSectionSetDof(coordSection, cell, dof);CHKERRQ(ierr);
19380598e1a2SLisandro Dalcin           ierr = PetscSectionSetFieldDof(coordSection, cell, 0, dof);CHKERRQ(ierr);
1939f45c9589SStefano Zampini         }
1940f45c9589SStefano Zampini       }
1941f45c9589SStefano Zampini     }
19420598e1a2SLisandro Dalcin     for (v = numCells; v < numCells+numVerts; ++v) {
19430598e1a2SLisandro Dalcin       ierr = PetscSectionSetDof(coordSection, v, coordDim);CHKERRQ(ierr);
19440598e1a2SLisandro Dalcin       ierr = PetscSectionSetFieldDof(coordSection, v, 0, coordDim);CHKERRQ(ierr);
19450598e1a2SLisandro Dalcin     }
1946331830f3SMatthew G. Knepley     ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr);
1947066ea43fSLisandro Dalcin 
1948066ea43fSLisandro Dalcin     ierr = DMCreateLocalVector(cdm, &coordinates);CHKERRQ(ierr);
1949066ea43fSLisandro Dalcin     ierr = VecGetArray(coordinates, &pointCoords);CHKERRQ(ierr);
19500598e1a2SLisandro Dalcin     if (periodic) {
19510598e1a2SLisandro Dalcin       for (cell = 0; cell < numCells; ++cell) {
19520598e1a2SLisandro Dalcin         if (PetscUnlikely(PetscBTLookup(periodicCells, cell))) {
19530598e1a2SLisandro Dalcin           GmshElement *elem = mesh->elements + cell;
19540598e1a2SLisandro Dalcin           PetscInt off, node;
19550598e1a2SLisandro Dalcin           for (v = 0; v < elem->numVerts; ++v)
19560598e1a2SLisandro Dalcin             cone[v] = elem->nodes[v];
1957066ea43fSLisandro Dalcin           ierr = DMPlexReorderCell(cdm, cell, cone);CHKERRQ(ierr);
19580598e1a2SLisandro Dalcin           ierr = PetscSectionGetOffset(coordSection, cell, &off);CHKERRQ(ierr);
19590598e1a2SLisandro Dalcin           for (v = 0; v < elem->numVerts; ++v)
19600598e1a2SLisandro Dalcin             for (node = cone[v], d = 0; d < coordDim; ++d)
1961066ea43fSLisandro Dalcin               pointCoords[off++] = (PetscReal) coords[node*3+d];
1962331830f3SMatthew G. Knepley         }
1963331830f3SMatthew G. Knepley       }
1964331830f3SMatthew G. Knepley     }
1965066ea43fSLisandro Dalcin     ierr = PetscMalloc1(numVerts, &nodeMap);CHKERRQ(ierr);
19660598e1a2SLisandro Dalcin     for (n = 0; n < numNodes; n++)
19670598e1a2SLisandro Dalcin       if (mesh->vertexMap[n] >= 0)
1968066ea43fSLisandro Dalcin         nodeMap[mesh->vertexMap[n]] = n;
19690598e1a2SLisandro Dalcin     for (v = 0; v < numVerts; ++v) {
1970066ea43fSLisandro Dalcin       PetscInt off, node = nodeMap[v];
19710598e1a2SLisandro Dalcin       ierr = PetscSectionGetOffset(coordSection, numCells + v, &off);CHKERRQ(ierr);
19720598e1a2SLisandro Dalcin       for (d = 0; d < coordDim; ++d)
1973066ea43fSLisandro Dalcin         pointCoords[off+d] = (PetscReal) coords[node*3+d];
19740598e1a2SLisandro Dalcin     }
1975066ea43fSLisandro Dalcin     ierr = PetscFree(nodeMap);CHKERRQ(ierr);
1976066ea43fSLisandro Dalcin     ierr = VecRestoreArray(coordinates, &pointCoords);CHKERRQ(ierr);
1977066ea43fSLisandro Dalcin 
1978066ea43fSLisandro Dalcin   }
1979066ea43fSLisandro Dalcin 
1980066ea43fSLisandro Dalcin   ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr);
1981066ea43fSLisandro Dalcin   ierr = VecSetBlockSize(coordinates, coordDim);CHKERRQ(ierr);
1982331830f3SMatthew G. Knepley   ierr = DMSetCoordinatesLocal(*dm, coordinates);CHKERRQ(ierr);
19830598e1a2SLisandro Dalcin   ierr = VecDestroy(&coordinates);CHKERRQ(ierr);
198411c56cb0SLisandro Dalcin   ierr = DMSetPeriodicity(*dm, periodic, NULL, NULL, NULL);CHKERRQ(ierr);
198511c56cb0SLisandro Dalcin 
19860598e1a2SLisandro Dalcin   ierr = GmshMeshDestroy(&mesh);CHKERRQ(ierr);
19870598e1a2SLisandro Dalcin   ierr = PetscBTDestroy(&periodicVerts);CHKERRQ(ierr);
19880598e1a2SLisandro Dalcin   ierr = PetscBTDestroy(&periodicCells);CHKERRQ(ierr);
198911c56cb0SLisandro Dalcin 
1990066ea43fSLisandro Dalcin   if (highOrder && project)  {
1991066ea43fSLisandro Dalcin     PetscFE         fe;
1992066ea43fSLisandro Dalcin     const char      prefix[]   = "dm_plex_gmsh_project_";
1993066ea43fSLisandro Dalcin     PetscBool       continuity = periodic ? PETSC_FALSE : PETSC_TRUE;
1994066ea43fSLisandro Dalcin     PetscDTNodeType nodeType   = PETSCDTNODES_GAUSSJACOBI;
1995066ea43fSLisandro Dalcin 
1996066ea43fSLisandro Dalcin     if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */
1997066ea43fSLisandro Dalcin 
1998066ea43fSLisandro Dalcin     ierr = GmshCreateFE(comm, prefix, isSimplex, continuity, nodeType, dim, coordDim, order, &fe);CHKERRQ(ierr);
1999066ea43fSLisandro Dalcin     ierr = PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_project_fe_view");CHKERRQ(ierr);
2000066ea43fSLisandro Dalcin     ierr = DMProjectCoordinates(*dm, fe);CHKERRQ(ierr);
2001066ea43fSLisandro Dalcin     ierr = PetscFEDestroy(&fe);CHKERRQ(ierr);
2002066ea43fSLisandro Dalcin   }
2003066ea43fSLisandro Dalcin 
20040598e1a2SLisandro Dalcin   ierr = PetscLogEventEnd(DMPLEX_CreateGmsh,*dm,NULL,NULL,NULL);CHKERRQ(ierr);
2005331830f3SMatthew G. Knepley   PetscFunctionReturn(0);
2006331830f3SMatthew G. Knepley }
2007