xref: /petsc/src/dm/impls/plex/plexgmsh.c (revision 28b400f66ebc7ae0049166a2294dfcd3df27e64b)
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 
21394bad497SJacob Faibussowitsch #define GmshCellTypeCheck(ct) PetscMacroReturnStandard(                                        \
2140598e1a2SLisandro Dalcin     const int _ct_ = (int)ct;                                                                  \
21594bad497SJacob Faibussowitsch     PetscCheck(_ct_ >= 0 && _ct_ < (int)(sizeof(GmshCellMap)/sizeof(GmshCellMap[0])), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid Gmsh element type %d", _ct_); \
21694bad497SJacob Faibussowitsch     PetscCheck(GmshCellMap[_ct_].cellType == _ct_, PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported Gmsh element type %d", _ct_); \
21794bad497SJacob Faibussowitsch     PetscCheck(GmshCellMap[_ct_].polytope != -1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported Gmsh element type %d", _ct_); \
21894bad497SJacob Faibussowitsch   )
2190598e1a2SLisandro Dalcin 
2200598e1a2SLisandro Dalcin typedef struct {
221698a79b9SLisandro Dalcin   PetscViewer  viewer;
222698a79b9SLisandro Dalcin   int          fileFormat;
223698a79b9SLisandro Dalcin   int          dataSize;
224698a79b9SLisandro Dalcin   PetscBool    binary;
225698a79b9SLisandro Dalcin   PetscBool    byteSwap;
226698a79b9SLisandro Dalcin   size_t       wlen;
227698a79b9SLisandro Dalcin   void        *wbuf;
228698a79b9SLisandro Dalcin   size_t       slen;
229698a79b9SLisandro Dalcin   void        *sbuf;
2300598e1a2SLisandro Dalcin   PetscInt    *nbuf;
2310598e1a2SLisandro Dalcin   PetscInt     nodeStart;
2320598e1a2SLisandro Dalcin   PetscInt     nodeEnd;
23333a088b6SMatthew G. Knepley   PetscInt    *nodeMap;
234698a79b9SLisandro Dalcin } GmshFile;
235de78e4feSLisandro Dalcin 
236698a79b9SLisandro Dalcin static PetscErrorCode GmshBufferGet(GmshFile *gmsh, size_t count, size_t eltsize, void *buf)
237de78e4feSLisandro Dalcin {
238de78e4feSLisandro Dalcin   size_t         size = count * eltsize;
23911c56cb0SLisandro Dalcin 
24011c56cb0SLisandro Dalcin   PetscFunctionBegin;
241698a79b9SLisandro Dalcin   if (gmsh->wlen < size) {
2425f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(gmsh->wbuf));
2435f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc(size, &gmsh->wbuf));
244698a79b9SLisandro Dalcin     gmsh->wlen = size;
245de78e4feSLisandro Dalcin   }
246698a79b9SLisandro Dalcin   *(void**)buf = size ? gmsh->wbuf : NULL;
247de78e4feSLisandro Dalcin   PetscFunctionReturn(0);
248de78e4feSLisandro Dalcin }
249de78e4feSLisandro Dalcin 
250698a79b9SLisandro Dalcin static PetscErrorCode GmshBufferSizeGet(GmshFile *gmsh, size_t count, void *buf)
251698a79b9SLisandro Dalcin {
252698a79b9SLisandro Dalcin   size_t         dataSize = (size_t)gmsh->dataSize;
253698a79b9SLisandro Dalcin   size_t         size = count * dataSize;
254698a79b9SLisandro Dalcin 
255698a79b9SLisandro Dalcin   PetscFunctionBegin;
256698a79b9SLisandro Dalcin   if (gmsh->slen < size) {
2575f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(gmsh->sbuf));
2585f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc(size, &gmsh->sbuf));
259698a79b9SLisandro Dalcin     gmsh->slen = size;
260698a79b9SLisandro Dalcin   }
261698a79b9SLisandro Dalcin   *(void**)buf = size ? gmsh->sbuf : NULL;
262698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
263698a79b9SLisandro Dalcin }
264698a79b9SLisandro Dalcin 
265698a79b9SLisandro Dalcin static PetscErrorCode GmshRead(GmshFile *gmsh, void *buf, PetscInt count, PetscDataType dtype)
266de78e4feSLisandro Dalcin {
267de78e4feSLisandro Dalcin   PetscFunctionBegin;
2685f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerRead(gmsh->viewer, buf, count, NULL, dtype));
2695f80ce2aSJacob Faibussowitsch   if (gmsh->byteSwap) CHKERRQ(PetscByteSwap(buf, dtype, count));
270698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
271698a79b9SLisandro Dalcin }
272698a79b9SLisandro Dalcin 
273698a79b9SLisandro Dalcin static PetscErrorCode GmshReadString(GmshFile *gmsh, char *buf, PetscInt count)
274698a79b9SLisandro Dalcin {
275698a79b9SLisandro Dalcin   PetscFunctionBegin;
2765f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerRead(gmsh->viewer, buf, count, NULL, PETSC_STRING));
277698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
278698a79b9SLisandro Dalcin }
279698a79b9SLisandro Dalcin 
280d6689ca9SLisandro Dalcin static PetscErrorCode GmshMatch(PETSC_UNUSED GmshFile *gmsh, const char Section[], char line[PETSC_MAX_PATH_LEN], PetscBool *match)
281d6689ca9SLisandro Dalcin {
282d6689ca9SLisandro Dalcin   PetscFunctionBegin;
2835f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(line, Section, match));
284d6689ca9SLisandro Dalcin   PetscFunctionReturn(0);
285d6689ca9SLisandro Dalcin }
286d6689ca9SLisandro Dalcin 
287d6689ca9SLisandro Dalcin static PetscErrorCode GmshExpect(GmshFile *gmsh, const char Section[], char line[PETSC_MAX_PATH_LEN])
288d6689ca9SLisandro Dalcin {
289d6689ca9SLisandro Dalcin   PetscBool      match;
290d6689ca9SLisandro Dalcin 
291d6689ca9SLisandro Dalcin   PetscFunctionBegin;
2925f80ce2aSJacob Faibussowitsch   CHKERRQ(GmshMatch(gmsh, Section, line, &match));
293*28b400f6SJacob Faibussowitsch   PetscCheck(match,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file, expecting %s",Section);
294d6689ca9SLisandro Dalcin   PetscFunctionReturn(0);
295d6689ca9SLisandro Dalcin }
296d6689ca9SLisandro Dalcin 
297d6689ca9SLisandro Dalcin static PetscErrorCode GmshReadSection(GmshFile *gmsh, char line[PETSC_MAX_PATH_LEN])
298d6689ca9SLisandro Dalcin {
299d6689ca9SLisandro Dalcin   PetscBool      match;
300d6689ca9SLisandro Dalcin 
301d6689ca9SLisandro Dalcin   PetscFunctionBegin;
302d6689ca9SLisandro Dalcin   while (PETSC_TRUE) {
3035f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshReadString(gmsh, line, 1));
3045f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshMatch(gmsh, "$Comments", line, &match));
305d6689ca9SLisandro Dalcin     if (!match) break;
306d6689ca9SLisandro Dalcin     while (PETSC_TRUE) {
3075f80ce2aSJacob Faibussowitsch       CHKERRQ(GmshReadString(gmsh, line, 1));
3085f80ce2aSJacob Faibussowitsch       CHKERRQ(GmshMatch(gmsh, "$EndComments", line, &match));
309d6689ca9SLisandro Dalcin       if (match) break;
310d6689ca9SLisandro Dalcin     }
311d6689ca9SLisandro Dalcin   }
312d6689ca9SLisandro Dalcin   PetscFunctionReturn(0);
313d6689ca9SLisandro Dalcin }
314d6689ca9SLisandro Dalcin 
315d6689ca9SLisandro Dalcin static PetscErrorCode GmshReadEndSection(GmshFile *gmsh, const char EndSection[], char line[PETSC_MAX_PATH_LEN])
316d6689ca9SLisandro Dalcin {
317d6689ca9SLisandro Dalcin   PetscFunctionBegin;
3185f80ce2aSJacob Faibussowitsch   CHKERRQ(GmshReadString(gmsh, line, 1));
3195f80ce2aSJacob Faibussowitsch   CHKERRQ(GmshExpect(gmsh, EndSection, line));
320d6689ca9SLisandro Dalcin   PetscFunctionReturn(0);
321d6689ca9SLisandro Dalcin }
322d6689ca9SLisandro Dalcin 
323698a79b9SLisandro Dalcin static PetscErrorCode GmshReadSize(GmshFile *gmsh, PetscInt *buf, PetscInt count)
324698a79b9SLisandro Dalcin {
325698a79b9SLisandro Dalcin   PetscInt       i;
326698a79b9SLisandro Dalcin   size_t         dataSize = (size_t)gmsh->dataSize;
327698a79b9SLisandro Dalcin 
328698a79b9SLisandro Dalcin   PetscFunctionBegin;
329698a79b9SLisandro Dalcin   if (dataSize == sizeof(PetscInt)) {
3305f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshRead(gmsh, buf, count, PETSC_INT));
331698a79b9SLisandro Dalcin   } else  if (dataSize == sizeof(int)) {
332698a79b9SLisandro Dalcin     int *ibuf = NULL;
3335f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshBufferSizeGet(gmsh, count, &ibuf));
3345f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshRead(gmsh, ibuf, count, PETSC_ENUM));
335698a79b9SLisandro Dalcin     for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i];
336698a79b9SLisandro Dalcin   } else  if (dataSize == sizeof(long)) {
337698a79b9SLisandro Dalcin     long *ibuf = NULL;
3385f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshBufferSizeGet(gmsh, count, &ibuf));
3395f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshRead(gmsh, ibuf, count, PETSC_LONG));
340698a79b9SLisandro Dalcin     for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i];
341698a79b9SLisandro Dalcin   } else if (dataSize == sizeof(PetscInt64)) {
342698a79b9SLisandro Dalcin     PetscInt64 *ibuf = NULL;
3435f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshBufferSizeGet(gmsh, count, &ibuf));
3445f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshRead(gmsh, ibuf, count, PETSC_INT64));
345698a79b9SLisandro Dalcin     for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i];
346698a79b9SLisandro Dalcin   }
347698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
348698a79b9SLisandro Dalcin }
349698a79b9SLisandro Dalcin 
350698a79b9SLisandro Dalcin static PetscErrorCode GmshReadInt(GmshFile *gmsh, int *buf, PetscInt count)
351698a79b9SLisandro Dalcin {
352698a79b9SLisandro Dalcin   PetscFunctionBegin;
3535f80ce2aSJacob Faibussowitsch   CHKERRQ(GmshRead(gmsh, buf, count, PETSC_ENUM));
354698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
355698a79b9SLisandro Dalcin }
356698a79b9SLisandro Dalcin 
357698a79b9SLisandro Dalcin static PetscErrorCode GmshReadDouble(GmshFile *gmsh, double *buf, PetscInt count)
358698a79b9SLisandro Dalcin {
359698a79b9SLisandro Dalcin   PetscFunctionBegin;
3605f80ce2aSJacob Faibussowitsch   CHKERRQ(GmshRead(gmsh, buf, count, PETSC_DOUBLE));
361de78e4feSLisandro Dalcin   PetscFunctionReturn(0);
362de78e4feSLisandro Dalcin }
363de78e4feSLisandro Dalcin 
364de78e4feSLisandro Dalcin typedef struct {
3650598e1a2SLisandro Dalcin   PetscInt id;       /* Entity ID */
3660598e1a2SLisandro Dalcin   PetscInt dim;      /* Dimension */
367de78e4feSLisandro Dalcin   double   bbox[6];  /* Bounding box */
368de78e4feSLisandro Dalcin   PetscInt numTags;  /* Size of tag array */
369de78e4feSLisandro Dalcin   int      tags[4];  /* Tag array */
370de78e4feSLisandro Dalcin } GmshEntity;
371de78e4feSLisandro Dalcin 
372de78e4feSLisandro Dalcin typedef struct {
373730356f6SLisandro Dalcin   GmshEntity *entity[4];
374730356f6SLisandro Dalcin   PetscHMapI  entityMap[4];
375730356f6SLisandro Dalcin } GmshEntities;
376730356f6SLisandro Dalcin 
377698a79b9SLisandro Dalcin static PetscErrorCode GmshEntitiesCreate(PetscInt count[4], GmshEntities **entities)
378730356f6SLisandro Dalcin {
379730356f6SLisandro Dalcin   PetscInt       dim;
380730356f6SLisandro Dalcin 
381730356f6SLisandro Dalcin   PetscFunctionBegin;
3825f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscNew(entities));
383730356f6SLisandro Dalcin   for (dim = 0; dim < 4; ++dim) {
3845f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscCalloc1(count[dim], &(*entities)->entity[dim]));
3855f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHMapICreate(&(*entities)->entityMap[dim]));
386730356f6SLisandro Dalcin   }
387730356f6SLisandro Dalcin   PetscFunctionReturn(0);
388730356f6SLisandro Dalcin }
389730356f6SLisandro Dalcin 
3900598e1a2SLisandro Dalcin static PetscErrorCode GmshEntitiesDestroy(GmshEntities **entities)
3910598e1a2SLisandro Dalcin {
3920598e1a2SLisandro Dalcin   PetscInt       dim;
3930598e1a2SLisandro Dalcin 
3940598e1a2SLisandro Dalcin   PetscFunctionBegin;
3950598e1a2SLisandro Dalcin   if (!*entities) PetscFunctionReturn(0);
3960598e1a2SLisandro Dalcin   for (dim = 0; dim < 4; ++dim) {
3975f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree((*entities)->entity[dim]));
3985f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHMapIDestroy(&(*entities)->entityMap[dim]));
3990598e1a2SLisandro Dalcin   }
4005f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree((*entities)));
4010598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
4020598e1a2SLisandro Dalcin }
4030598e1a2SLisandro Dalcin 
404730356f6SLisandro Dalcin static PetscErrorCode GmshEntitiesAdd(GmshEntities *entities, PetscInt index, PetscInt dim, PetscInt eid, GmshEntity** entity)
405730356f6SLisandro Dalcin {
406730356f6SLisandro Dalcin   PetscFunctionBegin;
4075f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscHMapISet(entities->entityMap[dim], eid, index));
408730356f6SLisandro Dalcin   entities->entity[dim][index].dim = dim;
409730356f6SLisandro Dalcin   entities->entity[dim][index].id  = eid;
410730356f6SLisandro Dalcin   if (entity) *entity = &entities->entity[dim][index];
411730356f6SLisandro Dalcin   PetscFunctionReturn(0);
412730356f6SLisandro Dalcin }
413730356f6SLisandro Dalcin 
414730356f6SLisandro Dalcin static PetscErrorCode GmshEntitiesGet(GmshEntities *entities, PetscInt dim, PetscInt eid, GmshEntity** entity)
415730356f6SLisandro Dalcin {
416730356f6SLisandro Dalcin   PetscInt       index;
417730356f6SLisandro Dalcin 
418730356f6SLisandro Dalcin   PetscFunctionBegin;
4195f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscHMapIGet(entities->entityMap[dim], eid, &index));
420730356f6SLisandro Dalcin   *entity = &entities->entity[dim][index];
421730356f6SLisandro Dalcin   PetscFunctionReturn(0);
422730356f6SLisandro Dalcin }
423730356f6SLisandro Dalcin 
4240598e1a2SLisandro Dalcin typedef struct {
4250598e1a2SLisandro Dalcin   PetscInt *id;  /* Node IDs */
4260598e1a2SLisandro Dalcin   double   *xyz; /* Coordinates */
42781a1af93SMatthew G. Knepley   PetscInt *tag; /* Physical tag */
4280598e1a2SLisandro Dalcin } GmshNodes;
4290598e1a2SLisandro Dalcin 
4300598e1a2SLisandro Dalcin static PetscErrorCode GmshNodesCreate(PetscInt count, GmshNodes **nodes)
431730356f6SLisandro Dalcin {
432730356f6SLisandro Dalcin   PetscFunctionBegin;
4335f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscNew(nodes));
4345f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(count*1, &(*nodes)->id));
4355f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(count*3, &(*nodes)->xyz));
4365f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(count*1, &(*nodes)->tag));
4370598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
438730356f6SLisandro Dalcin }
4390598e1a2SLisandro Dalcin 
4400598e1a2SLisandro Dalcin static PetscErrorCode GmshNodesDestroy(GmshNodes **nodes)
4410598e1a2SLisandro Dalcin {
4420598e1a2SLisandro Dalcin   PetscFunctionBegin;
4430598e1a2SLisandro Dalcin   if (!*nodes) PetscFunctionReturn(0);
4445f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree((*nodes)->id));
4455f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree((*nodes)->xyz));
4465f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree((*nodes)->tag));
4475f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree((*nodes)));
448730356f6SLisandro Dalcin   PetscFunctionReturn(0);
449730356f6SLisandro Dalcin }
450730356f6SLisandro Dalcin 
451730356f6SLisandro Dalcin typedef struct {
4520598e1a2SLisandro Dalcin   PetscInt id;       /* Element ID */
4530598e1a2SLisandro Dalcin   PetscInt dim;      /* Dimension */
454de78e4feSLisandro Dalcin   PetscInt cellType; /* Cell type */
4550598e1a2SLisandro Dalcin   PetscInt numVerts; /* Size of vertex array */
456de78e4feSLisandro Dalcin   PetscInt numNodes; /* Size of node array */
4570598e1a2SLisandro Dalcin   PetscInt *nodes;   /* Vertex/Node array */
45881a1af93SMatthew G. Knepley   PetscInt numTags;  /* Size of physical tag array */
45981a1af93SMatthew G. Knepley   int      tags[4];  /* Physical tag array */
460de78e4feSLisandro Dalcin } GmshElement;
461de78e4feSLisandro Dalcin 
4620598e1a2SLisandro Dalcin static PetscErrorCode GmshElementsCreate(PetscInt count, GmshElement **elements)
4630598e1a2SLisandro Dalcin {
4640598e1a2SLisandro Dalcin   PetscFunctionBegin;
4655f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCalloc1(count, elements));
4660598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
4670598e1a2SLisandro Dalcin }
4680598e1a2SLisandro Dalcin 
4690598e1a2SLisandro Dalcin static PetscErrorCode GmshElementsDestroy(GmshElement **elements)
4700598e1a2SLisandro Dalcin {
4710598e1a2SLisandro Dalcin   PetscFunctionBegin;
4720598e1a2SLisandro Dalcin   if (!*elements) PetscFunctionReturn(0);
4735f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(*elements));
4740598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
4750598e1a2SLisandro Dalcin }
4760598e1a2SLisandro Dalcin 
4770598e1a2SLisandro Dalcin typedef struct {
4780598e1a2SLisandro Dalcin   PetscInt       dim;
479066ea43fSLisandro Dalcin   PetscInt       order;
4800598e1a2SLisandro Dalcin   GmshEntities  *entities;
4810598e1a2SLisandro Dalcin   PetscInt       numNodes;
4820598e1a2SLisandro Dalcin   GmshNodes     *nodelist;
4830598e1a2SLisandro Dalcin   PetscInt       numElems;
4840598e1a2SLisandro Dalcin   GmshElement   *elements;
4850598e1a2SLisandro Dalcin   PetscInt       numVerts;
4860598e1a2SLisandro Dalcin   PetscInt       numCells;
4870598e1a2SLisandro Dalcin   PetscInt      *periodMap;
4880598e1a2SLisandro Dalcin   PetscInt      *vertexMap;
4890598e1a2SLisandro Dalcin   PetscSegBuffer segbuf;
490a45dabc8SMatthew G. Knepley   PetscInt       numRegions;
491a45dabc8SMatthew G. Knepley   PetscInt      *regionTags;
492a45dabc8SMatthew G. Knepley   char         **regionNames;
4930598e1a2SLisandro Dalcin } GmshMesh;
4940598e1a2SLisandro Dalcin 
4950598e1a2SLisandro Dalcin static PetscErrorCode GmshMeshCreate(GmshMesh **mesh)
4960598e1a2SLisandro Dalcin {
4970598e1a2SLisandro Dalcin   PetscFunctionBegin;
4985f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscNew(mesh));
4995f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSegBufferCreate(sizeof(PetscInt), 0, &(*mesh)->segbuf));
5000598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
5010598e1a2SLisandro Dalcin }
5020598e1a2SLisandro Dalcin 
5030598e1a2SLisandro Dalcin static PetscErrorCode GmshMeshDestroy(GmshMesh **mesh)
5040598e1a2SLisandro Dalcin {
505a45dabc8SMatthew G. Knepley   PetscInt       r;
5060598e1a2SLisandro Dalcin 
5070598e1a2SLisandro Dalcin   PetscFunctionBegin;
5080598e1a2SLisandro Dalcin   if (!*mesh) PetscFunctionReturn(0);
5095f80ce2aSJacob Faibussowitsch   CHKERRQ(GmshEntitiesDestroy(&(*mesh)->entities));
5105f80ce2aSJacob Faibussowitsch   CHKERRQ(GmshNodesDestroy(&(*mesh)->nodelist));
5115f80ce2aSJacob Faibussowitsch   CHKERRQ(GmshElementsDestroy(&(*mesh)->elements));
5125f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree((*mesh)->periodMap));
5135f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree((*mesh)->vertexMap));
5145f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSegBufferDestroy(&(*mesh)->segbuf));
5155f80ce2aSJacob Faibussowitsch   for (r = 0; r < (*mesh)->numRegions; ++r) CHKERRQ(PetscFree((*mesh)->regionNames[r]));
5165f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree2((*mesh)->regionTags, (*mesh)->regionNames));
5175f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree((*mesh)));
5180598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
5190598e1a2SLisandro Dalcin }
5200598e1a2SLisandro Dalcin 
5210598e1a2SLisandro Dalcin static PetscErrorCode GmshReadNodes_v22(GmshFile *gmsh, GmshMesh *mesh)
522de78e4feSLisandro Dalcin {
523698a79b9SLisandro Dalcin   PetscViewer    viewer = gmsh->viewer;
524698a79b9SLisandro Dalcin   PetscBool      byteSwap = gmsh->byteSwap;
525de78e4feSLisandro Dalcin   char           line[PETSC_MAX_PATH_LEN];
5260598e1a2SLisandro Dalcin   int            n, num, nid, snum;
5270598e1a2SLisandro Dalcin   GmshNodes      *nodes;
528de78e4feSLisandro Dalcin 
529de78e4feSLisandro Dalcin   PetscFunctionBegin;
5305f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING));
531698a79b9SLisandro Dalcin   snum = sscanf(line, "%d", &num);
5322c71b3e2SJacob Faibussowitsch   PetscCheckFalse(snum != 1,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
5335f80ce2aSJacob Faibussowitsch   CHKERRQ(GmshNodesCreate(num, &nodes));
5340598e1a2SLisandro Dalcin   mesh->numNodes = num;
5350598e1a2SLisandro Dalcin   mesh->nodelist = nodes;
5360598e1a2SLisandro Dalcin   for (n = 0; n < num; ++n) {
5370598e1a2SLisandro Dalcin     double *xyz = nodes->xyz + n*3;
5385f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM));
5395f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE));
5405f80ce2aSJacob Faibussowitsch     if (byteSwap) CHKERRQ(PetscByteSwap(&nid, PETSC_ENUM, 1));
5415f80ce2aSJacob Faibussowitsch     if (byteSwap) CHKERRQ(PetscByteSwap(xyz, PETSC_DOUBLE, 3));
5420598e1a2SLisandro Dalcin     nodes->id[n] = nid;
54381a1af93SMatthew G. Knepley     nodes->tag[n] = -1;
54411c56cb0SLisandro Dalcin   }
54511c56cb0SLisandro Dalcin   PetscFunctionReturn(0);
54611c56cb0SLisandro Dalcin }
54711c56cb0SLisandro Dalcin 
548de78e4feSLisandro Dalcin /* Gmsh elements can be of any dimension/co-dimension, so we need to traverse the
549de78e4feSLisandro Dalcin    file contents multiple times to figure out the true number of cells and facets
550de78e4feSLisandro Dalcin    in the given mesh. To make this more efficient we read the file contents only
551de78e4feSLisandro Dalcin    once and store them in memory, while determining the true number of cells. */
5520598e1a2SLisandro Dalcin static PetscErrorCode GmshReadElements_v22(GmshFile* gmsh, GmshMesh *mesh)
55311c56cb0SLisandro Dalcin {
554698a79b9SLisandro Dalcin   PetscViewer    viewer = gmsh->viewer;
555698a79b9SLisandro Dalcin   PetscBool      binary = gmsh->binary;
556698a79b9SLisandro Dalcin   PetscBool      byteSwap = gmsh->byteSwap;
557de78e4feSLisandro Dalcin   char           line[PETSC_MAX_PATH_LEN];
5580598e1a2SLisandro Dalcin   int            i, c, p, num, ibuf[1+4+1000], snum;
5590598e1a2SLisandro Dalcin   int            cellType, numElem, numVerts, numNodes, numTags;
560df032b82SMatthew G. Knepley   GmshElement   *elements;
5610598e1a2SLisandro Dalcin   PetscInt      *nodeMap = gmsh->nodeMap;
562df032b82SMatthew G. Knepley 
563df032b82SMatthew G. Knepley   PetscFunctionBegin;
5645f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING));
565698a79b9SLisandro Dalcin   snum = sscanf(line, "%d", &num);
5662c71b3e2SJacob Faibussowitsch   PetscCheckFalse(snum != 1,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
5675f80ce2aSJacob Faibussowitsch   CHKERRQ(GmshElementsCreate(num, &elements));
5680598e1a2SLisandro Dalcin   mesh->numElems = num;
5690598e1a2SLisandro Dalcin   mesh->elements = elements;
570698a79b9SLisandro Dalcin   for (c = 0; c < num;) {
5715f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM));
5725f80ce2aSJacob Faibussowitsch     if (byteSwap) CHKERRQ(PetscByteSwap(ibuf, PETSC_ENUM, 3));
5730598e1a2SLisandro Dalcin 
5740598e1a2SLisandro Dalcin     cellType = binary ? ibuf[0] : ibuf[1];
5750598e1a2SLisandro Dalcin     numElem  = binary ? ibuf[1] : 1;
576df032b82SMatthew G. Knepley     numTags  = ibuf[2];
5770598e1a2SLisandro Dalcin 
5785f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshCellTypeCheck(cellType));
5790598e1a2SLisandro Dalcin     numVerts = GmshCellMap[cellType].numVerts;
5800598e1a2SLisandro Dalcin     numNodes = GmshCellMap[cellType].numNodes;
5810598e1a2SLisandro Dalcin 
582df032b82SMatthew G. Knepley     for (i = 0; i < numElem; ++i, ++c) {
5830598e1a2SLisandro Dalcin       GmshElement *element = elements + c;
5840598e1a2SLisandro Dalcin       const int off = binary ? 0 : 1, nint = 1 + numTags + numNodes - off;
5850598e1a2SLisandro Dalcin       const int *id = ibuf, *nodes = ibuf + 1 + numTags, *tags = ibuf + 1;
5865f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerRead(viewer, ibuf+off, nint, NULL, PETSC_ENUM));
5875f80ce2aSJacob Faibussowitsch       if (byteSwap) CHKERRQ(PetscByteSwap(ibuf+off, PETSC_ENUM, nint));
5880598e1a2SLisandro Dalcin       element->id  = id[0];
5890598e1a2SLisandro Dalcin       element->dim = GmshCellMap[cellType].dim;
5900598e1a2SLisandro Dalcin       element->cellType = cellType;
5910598e1a2SLisandro Dalcin       element->numVerts = numVerts;
5920598e1a2SLisandro Dalcin       element->numNodes = numNodes;
5930598e1a2SLisandro Dalcin       element->numTags  = PetscMin(numTags, 4);
5945f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes));
5950598e1a2SLisandro Dalcin       for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]];
5960598e1a2SLisandro Dalcin       for (p = 0; p < element->numTags;  p++) element->tags[p]  = tags[p];
597df032b82SMatthew G. Knepley     }
598df032b82SMatthew G. Knepley   }
599df032b82SMatthew G. Knepley   PetscFunctionReturn(0);
600df032b82SMatthew G. Knepley }
6017d282ae0SMichael Lange 
602de78e4feSLisandro Dalcin /*
603de78e4feSLisandro Dalcin $Entities
604de78e4feSLisandro Dalcin   numPoints(unsigned long) numCurves(unsigned long)
605de78e4feSLisandro Dalcin     numSurfaces(unsigned long) numVolumes(unsigned long)
606de78e4feSLisandro Dalcin   // points
607de78e4feSLisandro Dalcin   tag(int) boxMinX(double) boxMinY(double) boxMinZ(double)
608de78e4feSLisandro Dalcin     boxMaxX(double) boxMaxY(double) boxMaxZ(double)
609de78e4feSLisandro Dalcin     numPhysicals(unsigned long) phyisicalTag[...](int)
610de78e4feSLisandro Dalcin   ...
611de78e4feSLisandro Dalcin   // curves
612de78e4feSLisandro Dalcin   tag(int) boxMinX(double) boxMinY(double) boxMinZ(double)
613de78e4feSLisandro Dalcin      boxMaxX(double) boxMaxY(double) boxMaxZ(double)
614de78e4feSLisandro Dalcin      numPhysicals(unsigned long) physicalTag[...](int)
615de78e4feSLisandro Dalcin      numBREPVert(unsigned long) tagBREPVert[...](int)
616de78e4feSLisandro Dalcin   ...
617de78e4feSLisandro Dalcin   // surfaces
618de78e4feSLisandro Dalcin   tag(int) boxMinX(double) boxMinY(double) boxMinZ(double)
619de78e4feSLisandro Dalcin     boxMaxX(double) boxMaxY(double) boxMaxZ(double)
620de78e4feSLisandro Dalcin     numPhysicals(unsigned long) physicalTag[...](int)
621de78e4feSLisandro Dalcin     numBREPCurve(unsigned long) tagBREPCurve[...](int)
622de78e4feSLisandro Dalcin   ...
623de78e4feSLisandro Dalcin   // volumes
624de78e4feSLisandro Dalcin   tag(int) boxMinX(double) boxMinY(double) boxMinZ(double)
625de78e4feSLisandro Dalcin     boxMaxX(double) boxMaxY(double) boxMaxZ(double)
626de78e4feSLisandro Dalcin     numPhysicals(unsigned long) physicalTag[...](int)
627de78e4feSLisandro Dalcin     numBREPSurfaces(unsigned long) tagBREPSurfaces[...](int)
628de78e4feSLisandro Dalcin   ...
629de78e4feSLisandro Dalcin $EndEntities
630de78e4feSLisandro Dalcin */
6310598e1a2SLisandro Dalcin static PetscErrorCode GmshReadEntities_v40(GmshFile *gmsh, GmshMesh *mesh)
632de78e4feSLisandro Dalcin {
633698a79b9SLisandro Dalcin   PetscViewer    viewer = gmsh->viewer;
634698a79b9SLisandro Dalcin   PetscBool      byteSwap = gmsh->byteSwap;
635698a79b9SLisandro Dalcin   long           index, num, lbuf[4];
636730356f6SLisandro Dalcin   int            dim, eid, numTags, *ibuf, t;
637698a79b9SLisandro Dalcin   PetscInt       count[4], i;
638a5ba3d71SLisandro Dalcin   GmshEntity     *entity = NULL;
639de78e4feSLisandro Dalcin 
640de78e4feSLisandro Dalcin   PetscFunctionBegin;
6415f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerRead(viewer, lbuf, 4, NULL, PETSC_LONG));
6425f80ce2aSJacob Faibussowitsch   if (byteSwap) CHKERRQ(PetscByteSwap(lbuf, PETSC_LONG, 4));
643698a79b9SLisandro Dalcin   for (i = 0; i < 4; ++i) count[i] = lbuf[i];
6445f80ce2aSJacob Faibussowitsch   CHKERRQ(GmshEntitiesCreate(count, &mesh->entities));
645de78e4feSLisandro Dalcin   for (dim = 0; dim < 4; ++dim) {
646730356f6SLisandro Dalcin     for (index = 0; index < count[dim]; ++index) {
6475f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerRead(viewer, &eid, 1, NULL, PETSC_ENUM));
6485f80ce2aSJacob Faibussowitsch       if (byteSwap) CHKERRQ(PetscByteSwap(&eid, PETSC_ENUM, 1));
6495f80ce2aSJacob Faibussowitsch       CHKERRQ(GmshEntitiesAdd(mesh->entities, (PetscInt)index, dim, eid, &entity));
6505f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerRead(viewer, entity->bbox, 6, NULL, PETSC_DOUBLE));
6515f80ce2aSJacob Faibussowitsch       if (byteSwap) CHKERRQ(PetscByteSwap(entity->bbox, PETSC_DOUBLE, 6));
6525f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerRead(viewer, &num, 1, NULL, PETSC_LONG));
6535f80ce2aSJacob Faibussowitsch       if (byteSwap) CHKERRQ(PetscByteSwap(&num, PETSC_LONG, 1));
6545f80ce2aSJacob Faibussowitsch       CHKERRQ(GmshBufferGet(gmsh, num, sizeof(int), &ibuf));
6555f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerRead(viewer, ibuf, num, NULL, PETSC_ENUM));
6565f80ce2aSJacob Faibussowitsch       if (byteSwap) CHKERRQ(PetscByteSwap(ibuf, PETSC_ENUM, num));
657de78e4feSLisandro Dalcin       entity->numTags = numTags = (int) PetscMin(num, 4);
658de78e4feSLisandro Dalcin       for (t = 0; t < numTags; ++t) entity->tags[t] = ibuf[t];
659de78e4feSLisandro Dalcin       if (dim == 0) continue;
6605f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerRead(viewer, &num, 1, NULL, PETSC_LONG));
6615f80ce2aSJacob Faibussowitsch       if (byteSwap) CHKERRQ(PetscByteSwap(&num, PETSC_LONG, 1));
6625f80ce2aSJacob Faibussowitsch       CHKERRQ(GmshBufferGet(gmsh, num, sizeof(int), &ibuf));
6635f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerRead(viewer, ibuf, num, NULL, PETSC_ENUM));
6645f80ce2aSJacob Faibussowitsch       if (byteSwap) CHKERRQ(PetscByteSwap(ibuf, PETSC_ENUM, num));
665de78e4feSLisandro Dalcin     }
666de78e4feSLisandro Dalcin   }
667de78e4feSLisandro Dalcin   PetscFunctionReturn(0);
668de78e4feSLisandro Dalcin }
669de78e4feSLisandro Dalcin 
670de78e4feSLisandro Dalcin /*
671de78e4feSLisandro Dalcin $Nodes
672de78e4feSLisandro Dalcin   numEntityBlocks(unsigned long) numNodes(unsigned long)
673de78e4feSLisandro Dalcin   tagEntity(int) dimEntity(int) typeNode(int) numNodes(unsigned long)
674de78e4feSLisandro Dalcin     tag(int) x(double) y(double) z(double)
675de78e4feSLisandro Dalcin     ...
676de78e4feSLisandro Dalcin   ...
677de78e4feSLisandro Dalcin $EndNodes
678de78e4feSLisandro Dalcin */
6790598e1a2SLisandro Dalcin static PetscErrorCode GmshReadNodes_v40(GmshFile *gmsh, GmshMesh *mesh)
680de78e4feSLisandro Dalcin {
681698a79b9SLisandro Dalcin   PetscViewer    viewer = gmsh->viewer;
682698a79b9SLisandro Dalcin   PetscBool      byteSwap = gmsh->byteSwap;
6830598e1a2SLisandro Dalcin   long           block, node, n, numEntityBlocks, numTotalNodes, numNodes;
684de78e4feSLisandro Dalcin   int            info[3], nid;
6850598e1a2SLisandro Dalcin   GmshNodes      *nodes;
686de78e4feSLisandro Dalcin 
687de78e4feSLisandro Dalcin   PetscFunctionBegin;
6885f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerRead(viewer, &numEntityBlocks, 1, NULL, PETSC_LONG));
6895f80ce2aSJacob Faibussowitsch   if (byteSwap) CHKERRQ(PetscByteSwap(&numEntityBlocks, PETSC_LONG, 1));
6905f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerRead(viewer, &numTotalNodes, 1, NULL, PETSC_LONG));
6915f80ce2aSJacob Faibussowitsch   if (byteSwap) CHKERRQ(PetscByteSwap(&numTotalNodes, PETSC_LONG, 1));
6925f80ce2aSJacob Faibussowitsch   CHKERRQ(GmshNodesCreate(numTotalNodes, &nodes));
6930598e1a2SLisandro Dalcin   mesh->numNodes = numTotalNodes;
6940598e1a2SLisandro Dalcin   mesh->nodelist = nodes;
6950598e1a2SLisandro Dalcin   for (n = 0, block = 0; block < numEntityBlocks; ++block) {
6965f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerRead(viewer, info, 3, NULL, PETSC_ENUM));
6975f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerRead(viewer, &numNodes, 1, NULL, PETSC_LONG));
6985f80ce2aSJacob Faibussowitsch     if (byteSwap) CHKERRQ(PetscByteSwap(&numNodes, PETSC_LONG, 1));
699698a79b9SLisandro Dalcin     if (gmsh->binary) {
700277f51e8SBarry Smith       size_t nbytes = sizeof(int) + 3*sizeof(double);
701277f51e8SBarry Smith       char   *cbuf = NULL; /* dummy value to prevent warning from compiler about possible unitilized value */
7025f80ce2aSJacob Faibussowitsch       CHKERRQ(GmshBufferGet(gmsh, numNodes, nbytes, &cbuf));
7035f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerRead(viewer, cbuf, numNodes*nbytes, NULL, PETSC_CHAR));
7040598e1a2SLisandro Dalcin       for (node = 0; node < numNodes; ++node, ++n) {
705de78e4feSLisandro Dalcin         char   *cnid = cbuf + node*nbytes, *cxyz = cnid + sizeof(int);
7060598e1a2SLisandro Dalcin         double *xyz = nodes->xyz + n*3;
7075f80ce2aSJacob Faibussowitsch         if (!PetscBinaryBigEndian()) CHKERRQ(PetscByteSwap(cnid, PETSC_ENUM, 1));
7085f80ce2aSJacob Faibussowitsch         if (!PetscBinaryBigEndian()) CHKERRQ(PetscByteSwap(cxyz, PETSC_DOUBLE, 3));
7095f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscMemcpy(&nid, cnid, sizeof(int)));
7105f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscMemcpy(xyz, cxyz, 3*sizeof(double)));
7115f80ce2aSJacob Faibussowitsch         if (byteSwap) CHKERRQ(PetscByteSwap(&nid, PETSC_ENUM, 1));
7125f80ce2aSJacob Faibussowitsch         if (byteSwap) CHKERRQ(PetscByteSwap(xyz, PETSC_DOUBLE, 3));
7130598e1a2SLisandro Dalcin         nodes->id[n] = nid;
71481a1af93SMatthew G. Knepley         nodes->tag[n] = -1;
715de78e4feSLisandro Dalcin       }
716de78e4feSLisandro Dalcin     } else {
7170598e1a2SLisandro Dalcin       for (node = 0; node < numNodes; ++node, ++n) {
7180598e1a2SLisandro Dalcin         double *xyz = nodes->xyz + n*3;
7195f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM));
7205f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE));
7215f80ce2aSJacob Faibussowitsch         if (byteSwap) CHKERRQ(PetscByteSwap(&nid, PETSC_ENUM, 1));
7225f80ce2aSJacob Faibussowitsch         if (byteSwap) CHKERRQ(PetscByteSwap(xyz, PETSC_DOUBLE, 3));
7230598e1a2SLisandro Dalcin         nodes->id[n] = nid;
72481a1af93SMatthew G. Knepley         nodes->tag[n] = -1;
725de78e4feSLisandro Dalcin       }
726de78e4feSLisandro Dalcin     }
727de78e4feSLisandro Dalcin   }
728de78e4feSLisandro Dalcin   PetscFunctionReturn(0);
729de78e4feSLisandro Dalcin }
730de78e4feSLisandro Dalcin 
731de78e4feSLisandro Dalcin /*
732de78e4feSLisandro Dalcin $Elements
733de78e4feSLisandro Dalcin   numEntityBlocks(unsigned long) numElements(unsigned long)
734de78e4feSLisandro Dalcin   tagEntity(int) dimEntity(int) typeEle(int) numElements(unsigned long)
735de78e4feSLisandro Dalcin     tag(int) numVert[...](int)
736de78e4feSLisandro Dalcin     ...
737de78e4feSLisandro Dalcin   ...
738de78e4feSLisandro Dalcin $EndElements
739de78e4feSLisandro Dalcin */
7400598e1a2SLisandro Dalcin static PetscErrorCode GmshReadElements_v40(GmshFile *gmsh, GmshMesh *mesh)
741de78e4feSLisandro Dalcin {
742698a79b9SLisandro Dalcin   PetscViewer    viewer = gmsh->viewer;
743698a79b9SLisandro Dalcin   PetscBool      byteSwap = gmsh->byteSwap;
744de78e4feSLisandro Dalcin   long           c, block, numEntityBlocks, numTotalElements, elem, numElements;
745de78e4feSLisandro Dalcin   int            p, info[3], *ibuf = NULL;
7460598e1a2SLisandro Dalcin   int            eid, dim, cellType, numVerts, numNodes, numTags;
747a5ba3d71SLisandro Dalcin   GmshEntity     *entity = NULL;
748de78e4feSLisandro Dalcin   GmshElement    *elements;
7490598e1a2SLisandro Dalcin   PetscInt       *nodeMap = gmsh->nodeMap;
750de78e4feSLisandro Dalcin 
751de78e4feSLisandro Dalcin   PetscFunctionBegin;
7525f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerRead(viewer, &numEntityBlocks, 1, NULL, PETSC_LONG));
7535f80ce2aSJacob Faibussowitsch   if (byteSwap) CHKERRQ(PetscByteSwap(&numEntityBlocks, PETSC_LONG, 1));
7545f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerRead(viewer, &numTotalElements, 1, NULL, PETSC_LONG));
7555f80ce2aSJacob Faibussowitsch   if (byteSwap) CHKERRQ(PetscByteSwap(&numTotalElements, PETSC_LONG, 1));
7565f80ce2aSJacob Faibussowitsch   CHKERRQ(GmshElementsCreate(numTotalElements, &elements));
7570598e1a2SLisandro Dalcin   mesh->numElems = numTotalElements;
7580598e1a2SLisandro Dalcin   mesh->elements = elements;
759de78e4feSLisandro Dalcin   for (c = 0, block = 0; block < numEntityBlocks; ++block) {
7605f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerRead(viewer, info, 3, NULL, PETSC_ENUM));
7615f80ce2aSJacob Faibussowitsch     if (byteSwap) CHKERRQ(PetscByteSwap(info, PETSC_ENUM, 3));
762de78e4feSLisandro Dalcin     eid = info[0]; dim = info[1]; cellType = info[2];
7635f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshEntitiesGet(mesh->entities, dim, eid, &entity));
7645f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshCellTypeCheck(cellType));
7650598e1a2SLisandro Dalcin     numVerts = GmshCellMap[cellType].numVerts;
7660598e1a2SLisandro Dalcin     numNodes = GmshCellMap[cellType].numNodes;
767730356f6SLisandro Dalcin     numTags  = entity->numTags;
7685f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerRead(viewer, &numElements, 1, NULL, PETSC_LONG));
7695f80ce2aSJacob Faibussowitsch     if (byteSwap) CHKERRQ(PetscByteSwap(&numElements, PETSC_LONG, 1));
7705f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshBufferGet(gmsh, (1+numNodes)*numElements, sizeof(int), &ibuf));
7715f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerRead(viewer, ibuf, (1+numNodes)*numElements, NULL, PETSC_ENUM));
7725f80ce2aSJacob Faibussowitsch     if (byteSwap) CHKERRQ(PetscByteSwap(ibuf, PETSC_ENUM, (1+numNodes)*numElements));
773de78e4feSLisandro Dalcin     for (elem = 0; elem < numElements; ++elem, ++c) {
774de78e4feSLisandro Dalcin       GmshElement *element = elements + c;
7750598e1a2SLisandro Dalcin       const int *id = ibuf + elem*(1+numNodes), *nodes = id + 1;
7760598e1a2SLisandro Dalcin       element->id  = id[0];
777de78e4feSLisandro Dalcin       element->dim = dim;
778de78e4feSLisandro Dalcin       element->cellType = cellType;
7790598e1a2SLisandro Dalcin       element->numVerts = numVerts;
780de78e4feSLisandro Dalcin       element->numNodes = numNodes;
781de78e4feSLisandro Dalcin       element->numTags  = numTags;
7825f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes));
7830598e1a2SLisandro Dalcin       for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]];
7840598e1a2SLisandro Dalcin       for (p = 0; p < element->numTags;  p++) element->tags[p]  = entity->tags[p];
785de78e4feSLisandro Dalcin     }
786de78e4feSLisandro Dalcin   }
787698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
788698a79b9SLisandro Dalcin }
789698a79b9SLisandro Dalcin 
7900598e1a2SLisandro Dalcin static PetscErrorCode GmshReadPeriodic_v40(GmshFile *gmsh, PetscInt periodicMap[])
791698a79b9SLisandro Dalcin {
792698a79b9SLisandro Dalcin   PetscViewer    viewer = gmsh->viewer;
793698a79b9SLisandro Dalcin   int            fileFormat = gmsh->fileFormat;
794698a79b9SLisandro Dalcin   PetscBool      binary = gmsh->binary;
795698a79b9SLisandro Dalcin   PetscBool      byteSwap = gmsh->byteSwap;
796698a79b9SLisandro Dalcin   int            numPeriodic, snum, i;
797698a79b9SLisandro Dalcin   char           line[PETSC_MAX_PATH_LEN];
7980598e1a2SLisandro Dalcin   PetscInt       *nodeMap = gmsh->nodeMap;
799698a79b9SLisandro Dalcin 
800698a79b9SLisandro Dalcin   PetscFunctionBegin;
801698a79b9SLisandro Dalcin   if (fileFormat == 22 || !binary) {
8025f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING));
803698a79b9SLisandro Dalcin     snum = sscanf(line, "%d", &numPeriodic);
8042c71b3e2SJacob Faibussowitsch     PetscCheckFalse(snum != 1,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
805698a79b9SLisandro Dalcin   } else {
8065f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerRead(viewer, &numPeriodic, 1, NULL, PETSC_ENUM));
8075f80ce2aSJacob Faibussowitsch     if (byteSwap) CHKERRQ(PetscByteSwap(&numPeriodic, PETSC_ENUM, 1));
808698a79b9SLisandro Dalcin   }
809698a79b9SLisandro Dalcin   for (i = 0; i < numPeriodic; i++) {
8109dddd249SSatish Balay     int    ibuf[3], correspondingDim = -1, correspondingTag = -1, primaryTag = -1, correspondingNode, primaryNode;
811698a79b9SLisandro Dalcin     long   j, nNodes;
812698a79b9SLisandro Dalcin     double affine[16];
813698a79b9SLisandro Dalcin 
814698a79b9SLisandro Dalcin     if (fileFormat == 22 || !binary) {
8155f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerRead(viewer, line, 3, NULL, PETSC_STRING));
8169dddd249SSatish Balay       snum = sscanf(line, "%d %d %d", &correspondingDim, &correspondingTag, &primaryTag);
8172c71b3e2SJacob Faibussowitsch       PetscCheckFalse(snum != 3,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
818698a79b9SLisandro Dalcin     } else {
8195f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM));
8205f80ce2aSJacob Faibussowitsch       if (byteSwap) CHKERRQ(PetscByteSwap(ibuf, PETSC_ENUM, 3));
8219dddd249SSatish Balay       correspondingDim = ibuf[0]; correspondingTag = ibuf[1]; primaryTag = ibuf[2];
822698a79b9SLisandro Dalcin     }
8239dddd249SSatish Balay     (void)correspondingDim; (void)correspondingTag; (void)primaryTag; /* unused */
824698a79b9SLisandro Dalcin 
825698a79b9SLisandro Dalcin     if (fileFormat == 22 || !binary) {
8265f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING));
827698a79b9SLisandro Dalcin       snum = sscanf(line, "%ld", &nNodes);
8284c500f23SPierre Jolivet       if (snum != 1) { /* discard transformation and try again */
8295f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerRead(viewer, line, -PETSC_MAX_PATH_LEN, NULL, PETSC_STRING));
8305f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING));
831698a79b9SLisandro Dalcin         snum = sscanf(line, "%ld", &nNodes);
8322c71b3e2SJacob Faibussowitsch         PetscCheckFalse(snum != 1,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
833698a79b9SLisandro Dalcin       }
834698a79b9SLisandro Dalcin     } else {
8355f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerRead(viewer, &nNodes, 1, NULL, PETSC_LONG));
8365f80ce2aSJacob Faibussowitsch       if (byteSwap) CHKERRQ(PetscByteSwap(&nNodes, PETSC_LONG, 1));
8374c500f23SPierre Jolivet       if (nNodes == -1) { /* discard transformation and try again */
8385f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerRead(viewer, affine, 16, NULL, PETSC_DOUBLE));
8395f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerRead(viewer, &nNodes, 1, NULL, PETSC_LONG));
8405f80ce2aSJacob Faibussowitsch         if (byteSwap) CHKERRQ(PetscByteSwap(&nNodes, PETSC_LONG, 1));
841698a79b9SLisandro Dalcin       }
842698a79b9SLisandro Dalcin     }
843698a79b9SLisandro Dalcin 
844698a79b9SLisandro Dalcin     for (j = 0; j < nNodes; j++) {
845698a79b9SLisandro Dalcin       if (fileFormat == 22 || !binary) {
8465f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerRead(viewer, line, 2, NULL, PETSC_STRING));
8479dddd249SSatish Balay         snum = sscanf(line, "%d %d", &correspondingNode, &primaryNode);
8482c71b3e2SJacob Faibussowitsch         PetscCheckFalse(snum != 2,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
849698a79b9SLisandro Dalcin       } else {
8505f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerRead(viewer, ibuf, 2, NULL, PETSC_ENUM));
8515f80ce2aSJacob Faibussowitsch         if (byteSwap) CHKERRQ(PetscByteSwap(ibuf, PETSC_ENUM, 2));
8529dddd249SSatish Balay         correspondingNode = ibuf[0]; primaryNode = ibuf[1];
853698a79b9SLisandro Dalcin       }
8549dddd249SSatish Balay       correspondingNode  = (int) nodeMap[correspondingNode];
8559dddd249SSatish Balay       primaryNode = (int) nodeMap[primaryNode];
8569dddd249SSatish Balay       periodicMap[correspondingNode] = primaryNode;
857698a79b9SLisandro Dalcin     }
858698a79b9SLisandro Dalcin   }
859698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
860698a79b9SLisandro Dalcin }
861698a79b9SLisandro Dalcin 
8620598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
863698a79b9SLisandro Dalcin $Entities
864698a79b9SLisandro Dalcin   numPoints(size_t) numCurves(size_t)
865698a79b9SLisandro Dalcin     numSurfaces(size_t) numVolumes(size_t)
866698a79b9SLisandro Dalcin   pointTag(int) X(double) Y(double) Z(double)
867698a79b9SLisandro Dalcin     numPhysicalTags(size_t) physicalTag(int) ...
868698a79b9SLisandro Dalcin   ...
869698a79b9SLisandro Dalcin   curveTag(int) minX(double) minY(double) minZ(double)
870698a79b9SLisandro Dalcin     maxX(double) maxY(double) maxZ(double)
871698a79b9SLisandro Dalcin     numPhysicalTags(size_t) physicalTag(int) ...
872698a79b9SLisandro Dalcin     numBoundingPoints(size_t) pointTag(int) ...
873698a79b9SLisandro Dalcin   ...
874698a79b9SLisandro Dalcin   surfaceTag(int) minX(double) minY(double) minZ(double)
875698a79b9SLisandro Dalcin     maxX(double) maxY(double) maxZ(double)
876698a79b9SLisandro Dalcin     numPhysicalTags(size_t) physicalTag(int) ...
877698a79b9SLisandro Dalcin     numBoundingCurves(size_t) curveTag(int) ...
878698a79b9SLisandro Dalcin   ...
879698a79b9SLisandro Dalcin   volumeTag(int) minX(double) minY(double) minZ(double)
880698a79b9SLisandro Dalcin     maxX(double) maxY(double) maxZ(double)
881698a79b9SLisandro Dalcin     numPhysicalTags(size_t) physicalTag(int) ...
882698a79b9SLisandro Dalcin     numBoundngSurfaces(size_t) surfaceTag(int) ...
883698a79b9SLisandro Dalcin   ...
884698a79b9SLisandro Dalcin $EndEntities
885698a79b9SLisandro Dalcin */
8860598e1a2SLisandro Dalcin static PetscErrorCode GmshReadEntities_v41(GmshFile *gmsh, GmshMesh *mesh)
887698a79b9SLisandro Dalcin {
888698a79b9SLisandro Dalcin   PetscInt       count[4], index, numTags, i;
889698a79b9SLisandro Dalcin   int            dim, eid, *tags = NULL;
890698a79b9SLisandro Dalcin   GmshEntity     *entity = NULL;
891698a79b9SLisandro Dalcin 
892698a79b9SLisandro Dalcin   PetscFunctionBegin;
8935f80ce2aSJacob Faibussowitsch   CHKERRQ(GmshReadSize(gmsh, count, 4));
8945f80ce2aSJacob Faibussowitsch   CHKERRQ(GmshEntitiesCreate(count, &mesh->entities));
895698a79b9SLisandro Dalcin   for (dim = 0; dim < 4; ++dim) {
896698a79b9SLisandro Dalcin     for (index = 0; index < count[dim]; ++index) {
8975f80ce2aSJacob Faibussowitsch       CHKERRQ(GmshReadInt(gmsh, &eid, 1));
8985f80ce2aSJacob Faibussowitsch       CHKERRQ(GmshEntitiesAdd(mesh->entities, (PetscInt)index, dim, eid, &entity));
8995f80ce2aSJacob Faibussowitsch       CHKERRQ(GmshReadDouble(gmsh, entity->bbox, (dim == 0) ? 3 : 6));
9005f80ce2aSJacob Faibussowitsch       CHKERRQ(GmshReadSize(gmsh, &numTags, 1));
9015f80ce2aSJacob Faibussowitsch       CHKERRQ(GmshBufferGet(gmsh, numTags, sizeof(int), &tags));
9025f80ce2aSJacob Faibussowitsch       CHKERRQ(GmshReadInt(gmsh, tags, numTags));
903698a79b9SLisandro Dalcin       entity->numTags = PetscMin(numTags, 4);
904698a79b9SLisandro Dalcin       for (i = 0; i < entity->numTags; ++i) entity->tags[i] = tags[i];
905698a79b9SLisandro Dalcin       if (dim == 0) continue;
9065f80ce2aSJacob Faibussowitsch       CHKERRQ(GmshReadSize(gmsh, &numTags, 1));
9075f80ce2aSJacob Faibussowitsch       CHKERRQ(GmshBufferGet(gmsh, numTags, sizeof(int), &tags));
9085f80ce2aSJacob Faibussowitsch       CHKERRQ(GmshReadInt(gmsh, tags, numTags));
90981a1af93SMatthew G. Knepley       /* Currently, we do not save the ids for the bounding entities */
910698a79b9SLisandro Dalcin     }
911698a79b9SLisandro Dalcin   }
912698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
913698a79b9SLisandro Dalcin }
914698a79b9SLisandro Dalcin 
91533a088b6SMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
916698a79b9SLisandro Dalcin $Nodes
917698a79b9SLisandro Dalcin   numEntityBlocks(size_t) numNodes(size_t)
918698a79b9SLisandro Dalcin     minNodeTag(size_t) maxNodeTag(size_t)
919698a79b9SLisandro Dalcin   entityDim(int) entityTag(int) parametric(int; 0 or 1) numNodesBlock(size_t)
920698a79b9SLisandro Dalcin     nodeTag(size_t)
921698a79b9SLisandro Dalcin     ...
922698a79b9SLisandro Dalcin     x(double) y(double) z(double)
923698a79b9SLisandro Dalcin        < u(double; if parametric and entityDim = 1 or entityDim = 2) >
924698a79b9SLisandro Dalcin        < v(double; if parametric and entityDim = 2) >
925698a79b9SLisandro Dalcin     ...
926698a79b9SLisandro Dalcin   ...
927698a79b9SLisandro Dalcin $EndNodes
928698a79b9SLisandro Dalcin */
9290598e1a2SLisandro Dalcin static PetscErrorCode GmshReadNodes_v41(GmshFile *gmsh, GmshMesh *mesh)
930698a79b9SLisandro Dalcin {
93181a1af93SMatthew G. Knepley   int            info[3], dim, eid, parametric;
93281a1af93SMatthew G. Knepley   PetscInt       sizes[4], numEntityBlocks, numTags, numNodes, numNodesBlock = 0, block, node, n;
93381a1af93SMatthew G. Knepley   GmshEntity     *entity = NULL;
9340598e1a2SLisandro Dalcin   GmshNodes      *nodes;
935698a79b9SLisandro Dalcin 
936698a79b9SLisandro Dalcin   PetscFunctionBegin;
9375f80ce2aSJacob Faibussowitsch   CHKERRQ(GmshReadSize(gmsh, sizes, 4));
9380598e1a2SLisandro Dalcin   numEntityBlocks = sizes[0]; numNodes = sizes[1];
9395f80ce2aSJacob Faibussowitsch   CHKERRQ(GmshNodesCreate(numNodes, &nodes));
9400598e1a2SLisandro Dalcin   mesh->numNodes = numNodes;
9410598e1a2SLisandro Dalcin   mesh->nodelist = nodes;
942698a79b9SLisandro Dalcin   for (block = 0, node = 0; block < numEntityBlocks; ++block, node += numNodesBlock) {
9435f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshReadInt(gmsh, info, 3));
94481a1af93SMatthew G. Knepley     dim = info[0]; eid = info[1]; parametric = info[2];
9455f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshEntitiesGet(mesh->entities, dim, eid, &entity));
94681a1af93SMatthew G. Knepley     numTags = PetscMin(1, entity->numTags);
94781a1af93SMatthew G. Knepley     if (entity->numTags > 1) PetscInfo(NULL, "Entity %d has more than %d physical tags, assigning only the first to nodes", eid, 1);
94881a1af93SMatthew G. Knepley     PetscCheck(!parametric, PETSC_COMM_SELF, PETSC_ERR_SUP, "Parametric coordinates not supported");
9495f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshReadSize(gmsh, &numNodesBlock, 1));
9505f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshReadSize(gmsh, nodes->id+node, numNodesBlock));
9515f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshReadDouble(gmsh, nodes->xyz+node*3, numNodesBlock*3));
95281a1af93SMatthew G. Knepley     for (n = 0; n < numNodesBlock; ++n) nodes->tag[node+n] = numTags ? entity->tags[0] : -1;
953698a79b9SLisandro Dalcin   }
9540598e1a2SLisandro Dalcin   gmsh->nodeStart = sizes[2];
9550598e1a2SLisandro Dalcin   gmsh->nodeEnd   = sizes[3]+1;
956698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
957698a79b9SLisandro Dalcin }
958698a79b9SLisandro Dalcin 
95933a088b6SMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
960698a79b9SLisandro Dalcin $Elements
961698a79b9SLisandro Dalcin   numEntityBlocks(size_t) numElements(size_t)
962698a79b9SLisandro Dalcin     minElementTag(size_t) maxElementTag(size_t)
963698a79b9SLisandro Dalcin   entityDim(int) entityTag(int) elementType(int; see below) numElementsBlock(size_t)
964698a79b9SLisandro Dalcin     elementTag(size_t) nodeTag(size_t) ...
965698a79b9SLisandro Dalcin     ...
966698a79b9SLisandro Dalcin   ...
967698a79b9SLisandro Dalcin $EndElements
968698a79b9SLisandro Dalcin */
9690598e1a2SLisandro Dalcin static PetscErrorCode GmshReadElements_v41(GmshFile *gmsh, GmshMesh *mesh)
970698a79b9SLisandro Dalcin {
9710598e1a2SLisandro Dalcin   int            info[3], eid, dim, cellType;
9720598e1a2SLisandro Dalcin   PetscInt       sizes[4], *ibuf = NULL, numEntityBlocks, numElements, numBlockElements, numVerts, numNodes, numTags, block, elem, c, p;
973698a79b9SLisandro Dalcin   GmshEntity     *entity = NULL;
974698a79b9SLisandro Dalcin   GmshElement    *elements;
9750598e1a2SLisandro Dalcin   PetscInt       *nodeMap = gmsh->nodeMap;
976698a79b9SLisandro Dalcin 
977698a79b9SLisandro Dalcin   PetscFunctionBegin;
9785f80ce2aSJacob Faibussowitsch   CHKERRQ(GmshReadSize(gmsh, sizes, 4));
979698a79b9SLisandro Dalcin   numEntityBlocks = sizes[0]; numElements = sizes[1];
9805f80ce2aSJacob Faibussowitsch   CHKERRQ(GmshElementsCreate(numElements, &elements));
9810598e1a2SLisandro Dalcin   mesh->numElems = numElements;
9820598e1a2SLisandro Dalcin   mesh->elements = elements;
983698a79b9SLisandro Dalcin   for (c = 0, block = 0; block < numEntityBlocks; ++block) {
9845f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshReadInt(gmsh, info, 3));
985698a79b9SLisandro Dalcin     dim = info[0]; eid = info[1]; cellType = info[2];
9865f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshEntitiesGet(mesh->entities, dim, eid, &entity));
9875f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshCellTypeCheck(cellType));
9880598e1a2SLisandro Dalcin     numVerts = GmshCellMap[cellType].numVerts;
9890598e1a2SLisandro Dalcin     numNodes = GmshCellMap[cellType].numNodes;
99081a1af93SMatthew G. Knepley     numTags  = PetscMin(4, entity->numTags);
99181a1af93SMatthew G. Knepley     if (entity->numTags > 4) PetscInfo(NULL, "Entity %d has more then %d physical tags, assigning only the first to elements", eid, 4);
9925f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshReadSize(gmsh, &numBlockElements, 1));
9935f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshBufferGet(gmsh, (1+numNodes)*numBlockElements, sizeof(PetscInt), &ibuf));
9945f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshReadSize(gmsh, ibuf, (1+numNodes)*numBlockElements));
995698a79b9SLisandro Dalcin     for (elem = 0; elem < numBlockElements; ++elem, ++c) {
996698a79b9SLisandro Dalcin       GmshElement *element = elements + c;
9970598e1a2SLisandro Dalcin       const PetscInt *id = ibuf + elem*(1+numNodes), *nodes = id + 1;
998698a79b9SLisandro Dalcin       element->id  = id[0];
999698a79b9SLisandro Dalcin       element->dim = dim;
1000698a79b9SLisandro Dalcin       element->cellType = cellType;
10010598e1a2SLisandro Dalcin       element->numVerts = numVerts;
1002698a79b9SLisandro Dalcin       element->numNodes = numNodes;
1003698a79b9SLisandro Dalcin       element->numTags  = numTags;
10045f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes));
10050598e1a2SLisandro Dalcin       for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]];
10060598e1a2SLisandro Dalcin       for (p = 0; p < element->numTags;  p++) element->tags[p]  = entity->tags[p];
1007698a79b9SLisandro Dalcin     }
1008698a79b9SLisandro Dalcin   }
1009698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
1010698a79b9SLisandro Dalcin }
1011698a79b9SLisandro Dalcin 
10120598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
1013698a79b9SLisandro Dalcin $Periodic
1014698a79b9SLisandro Dalcin   numPeriodicLinks(size_t)
10159dddd249SSatish Balay   entityDim(int) entityTag(int) entityTagPrimary(int)
1016698a79b9SLisandro Dalcin   numAffine(size_t) value(double) ...
1017698a79b9SLisandro Dalcin   numCorrespondingNodes(size_t)
10189dddd249SSatish Balay     nodeTag(size_t) nodeTagPrimary(size_t)
1019698a79b9SLisandro Dalcin     ...
1020698a79b9SLisandro Dalcin   ...
1021698a79b9SLisandro Dalcin $EndPeriodic
1022698a79b9SLisandro Dalcin */
10230598e1a2SLisandro Dalcin static PetscErrorCode GmshReadPeriodic_v41(GmshFile *gmsh, PetscInt periodicMap[])
1024698a79b9SLisandro Dalcin {
1025698a79b9SLisandro Dalcin   int            info[3];
1026698a79b9SLisandro Dalcin   double         dbuf[16];
10270598e1a2SLisandro Dalcin   PetscInt       numPeriodicLinks, numAffine, numCorrespondingNodes, *nodeTags = NULL, link, node;
10280598e1a2SLisandro Dalcin   PetscInt       *nodeMap = gmsh->nodeMap;
1029698a79b9SLisandro Dalcin 
1030698a79b9SLisandro Dalcin   PetscFunctionBegin;
10315f80ce2aSJacob Faibussowitsch   CHKERRQ(GmshReadSize(gmsh, &numPeriodicLinks, 1));
1032698a79b9SLisandro Dalcin   for (link = 0; link < numPeriodicLinks; ++link) {
10335f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshReadInt(gmsh, info, 3));
10345f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshReadSize(gmsh, &numAffine, 1));
10355f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshReadDouble(gmsh, dbuf, numAffine));
10365f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshReadSize(gmsh, &numCorrespondingNodes, 1));
10375f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshBufferGet(gmsh, numCorrespondingNodes, sizeof(PetscInt), &nodeTags));
10385f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshReadSize(gmsh, nodeTags, numCorrespondingNodes*2));
1039698a79b9SLisandro Dalcin     for (node = 0; node < numCorrespondingNodes; ++node) {
10409dddd249SSatish Balay       PetscInt correspondingNode = nodeMap[nodeTags[node*2+0]];
10419dddd249SSatish Balay       PetscInt primaryNode = nodeMap[nodeTags[node*2+1]];
10429dddd249SSatish Balay       periodicMap[correspondingNode] = primaryNode;
1043698a79b9SLisandro Dalcin     }
1044698a79b9SLisandro Dalcin   }
1045698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
1046698a79b9SLisandro Dalcin }
1047698a79b9SLisandro Dalcin 
10480598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
1049d6689ca9SLisandro Dalcin $MeshFormat // same as MSH version 2
1050d6689ca9SLisandro Dalcin   version(ASCII double; currently 4.1)
1051d6689ca9SLisandro Dalcin   file-type(ASCII int; 0 for ASCII mode, 1 for binary mode)
1052d6689ca9SLisandro Dalcin   data-size(ASCII int; sizeof(size_t))
1053d6689ca9SLisandro Dalcin   < int with value one; only in binary mode, to detect endianness >
1054d6689ca9SLisandro Dalcin $EndMeshFormat
1055d6689ca9SLisandro Dalcin */
10560598e1a2SLisandro Dalcin static PetscErrorCode GmshReadMeshFormat(GmshFile *gmsh)
1057698a79b9SLisandro Dalcin {
1058698a79b9SLisandro Dalcin   char           line[PETSC_MAX_PATH_LEN];
1059698a79b9SLisandro Dalcin   int            snum, fileType, fileFormat, dataSize, checkEndian;
1060698a79b9SLisandro Dalcin   float          version;
1061698a79b9SLisandro Dalcin 
1062698a79b9SLisandro Dalcin   PetscFunctionBegin;
10635f80ce2aSJacob Faibussowitsch   CHKERRQ(GmshReadString(gmsh, line, 3));
1064698a79b9SLisandro Dalcin   snum = sscanf(line, "%f %d %d", &version, &fileType, &dataSize);
10652c71b3e2SJacob Faibussowitsch   PetscCheckFalse(snum != 3,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line);
10662c71b3e2SJacob Faibussowitsch   PetscCheckFalse(version < 2.2,PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at least 2.2", (double)version);
10672c71b3e2SJacob Faibussowitsch   PetscCheckFalse((int)version == 3,PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f not supported", (double)version);
10682c71b3e2SJacob Faibussowitsch   PetscCheckFalse(version > 4.1,PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at most 4.1", (double)version);
10692c71b3e2SJacob Faibussowitsch   PetscCheckFalse(gmsh->binary && !fileType,PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Viewer is binary but Gmsh file is ASCII");
10702c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!gmsh->binary && fileType,PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Viewer is ASCII but Gmsh file is binary");
1071af7a0b9fSSatish Balay   fileFormat = (int)roundf(version*10);
10722c71b3e2SJacob 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);
10732c71b3e2SJacob 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);
1074698a79b9SLisandro Dalcin   gmsh->fileFormat = fileFormat;
1075698a79b9SLisandro Dalcin   gmsh->dataSize = dataSize;
1076698a79b9SLisandro Dalcin   gmsh->byteSwap = PETSC_FALSE;
1077698a79b9SLisandro Dalcin   if (gmsh->binary) {
10785f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshReadInt(gmsh, &checkEndian, 1));
1079698a79b9SLisandro Dalcin     if (checkEndian != 1) {
10805f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscByteSwap(&checkEndian, PETSC_ENUM, 1));
10812c71b3e2SJacob Faibussowitsch       PetscCheckFalse(checkEndian != 1,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to detect endianness in Gmsh file header: %s", line);
1082698a79b9SLisandro Dalcin       gmsh->byteSwap = PETSC_TRUE;
1083698a79b9SLisandro Dalcin     }
1084698a79b9SLisandro Dalcin   }
1085698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
1086698a79b9SLisandro Dalcin }
1087698a79b9SLisandro Dalcin 
10881f643af3SLisandro Dalcin /*
10891f643af3SLisandro Dalcin PhysicalNames
10901f643af3SLisandro Dalcin   numPhysicalNames(ASCII int)
10911f643af3SLisandro Dalcin   dimension(ASCII int) physicalTag(ASCII int) "name"(127 characters max)
10921f643af3SLisandro Dalcin   ...
10931f643af3SLisandro Dalcin $EndPhysicalNames
10941f643af3SLisandro Dalcin */
1095a45dabc8SMatthew G. Knepley static PetscErrorCode GmshReadPhysicalNames(GmshFile *gmsh, GmshMesh *mesh)
1096698a79b9SLisandro Dalcin {
10971f643af3SLisandro Dalcin   char           line[PETSC_MAX_PATH_LEN], name[128+2], *p, *q;
1098a45dabc8SMatthew G. Knepley   int            snum, region, dim, tag;
1099698a79b9SLisandro Dalcin 
1100698a79b9SLisandro Dalcin   PetscFunctionBegin;
11015f80ce2aSJacob Faibussowitsch   CHKERRQ(GmshReadString(gmsh, line, 1));
1102a45dabc8SMatthew G. Knepley   snum = sscanf(line, "%d", &region);
1103a45dabc8SMatthew G. Knepley   mesh->numRegions = region;
11042c71b3e2SJacob Faibussowitsch   PetscCheckFalse(snum != 1,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
11055f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc2(mesh->numRegions, &mesh->regionTags, mesh->numRegions, &mesh->regionNames));
1106a45dabc8SMatthew G. Knepley   for (region = 0; region < mesh->numRegions; ++region) {
11075f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshReadString(gmsh, line, 2));
11081f643af3SLisandro Dalcin     snum = sscanf(line, "%d %d", &dim, &tag);
11092c71b3e2SJacob Faibussowitsch     PetscCheckFalse(snum != 2,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
11105f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshReadString(gmsh, line, -(PetscInt)sizeof(line)));
11115f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrchr(line, '"', &p));
1112*28b400f6SJacob Faibussowitsch     PetscCheck(p,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
11135f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrrchr(line, '"', &q));
11142c71b3e2SJacob Faibussowitsch     PetscCheckFalse(q == p,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
11155f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrncpy(name, p+1, (size_t)(q-p-1)));
1116a45dabc8SMatthew G. Knepley     mesh->regionTags[region] = tag;
11175f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrallocpy(name, &mesh->regionNames[region]));
1118698a79b9SLisandro Dalcin   }
1119de78e4feSLisandro Dalcin   PetscFunctionReturn(0);
1120de78e4feSLisandro Dalcin }
1121de78e4feSLisandro Dalcin 
11220598e1a2SLisandro Dalcin static PetscErrorCode GmshReadEntities(GmshFile *gmsh, GmshMesh *mesh)
112396ca5757SLisandro Dalcin {
11240598e1a2SLisandro Dalcin   PetscFunctionBegin;
11250598e1a2SLisandro Dalcin   switch (gmsh->fileFormat) {
11265f80ce2aSJacob Faibussowitsch   case 41: CHKERRQ(GmshReadEntities_v41(gmsh, mesh)); break;
11275f80ce2aSJacob Faibussowitsch   default: CHKERRQ(GmshReadEntities_v40(gmsh, mesh)); break;
112896ca5757SLisandro Dalcin   }
11290598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
11300598e1a2SLisandro Dalcin }
11310598e1a2SLisandro Dalcin 
11320598e1a2SLisandro Dalcin static PetscErrorCode GmshReadNodes(GmshFile *gmsh, GmshMesh *mesh)
11330598e1a2SLisandro Dalcin {
11340598e1a2SLisandro Dalcin   PetscFunctionBegin;
11350598e1a2SLisandro Dalcin   switch (gmsh->fileFormat) {
11365f80ce2aSJacob Faibussowitsch   case 41: CHKERRQ(GmshReadNodes_v41(gmsh, mesh)); break;
11375f80ce2aSJacob Faibussowitsch   case 40: CHKERRQ(GmshReadNodes_v40(gmsh, mesh)); break;
11385f80ce2aSJacob Faibussowitsch   default: CHKERRQ(GmshReadNodes_v22(gmsh, mesh)); break;
11390598e1a2SLisandro Dalcin   }
11400598e1a2SLisandro Dalcin 
11410598e1a2SLisandro Dalcin   { /* Gmsh v2.2/v4.0 does not provide min/max node tags */
11420598e1a2SLisandro Dalcin     if (mesh->numNodes > 0 && gmsh->nodeEnd >= gmsh->nodeStart) {
11430598e1a2SLisandro Dalcin       PetscInt  tagMin = PETSC_MAX_INT, tagMax = PETSC_MIN_INT, n;
11440598e1a2SLisandro Dalcin       GmshNodes *nodes = mesh->nodelist;
11450598e1a2SLisandro Dalcin       for (n = 0; n < mesh->numNodes; ++n) {
11460598e1a2SLisandro Dalcin         const PetscInt tag = nodes->id[n];
11470598e1a2SLisandro Dalcin         tagMin = PetscMin(tag, tagMin);
11480598e1a2SLisandro Dalcin         tagMax = PetscMax(tag, tagMax);
11490598e1a2SLisandro Dalcin       }
11500598e1a2SLisandro Dalcin       gmsh->nodeStart = tagMin;
11510598e1a2SLisandro Dalcin       gmsh->nodeEnd   = tagMax+1;
11520598e1a2SLisandro Dalcin     }
11530598e1a2SLisandro Dalcin   }
11540598e1a2SLisandro Dalcin 
11550598e1a2SLisandro Dalcin   { /* Support for sparse node tags */
11560598e1a2SLisandro Dalcin     PetscInt  n, t;
11570598e1a2SLisandro Dalcin     GmshNodes *nodes = mesh->nodelist;
11585f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(gmsh->nodeEnd - gmsh->nodeStart, &gmsh->nbuf));
11590598e1a2SLisandro Dalcin     for (t = 0; t < gmsh->nodeEnd - gmsh->nodeStart; ++t) gmsh->nbuf[t] = PETSC_MIN_INT;
11600598e1a2SLisandro Dalcin     gmsh->nodeMap = gmsh->nbuf - gmsh->nodeStart;
11610598e1a2SLisandro Dalcin     for (n = 0; n < mesh->numNodes; ++n) {
11620598e1a2SLisandro Dalcin       const PetscInt tag = nodes->id[n];
11632c71b3e2SJacob Faibussowitsch       PetscCheckFalse(gmsh->nodeMap[tag] >= 0,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Repeated node tag %D", tag);
11640598e1a2SLisandro Dalcin       gmsh->nodeMap[tag] = n;
11650598e1a2SLisandro Dalcin     }
11660598e1a2SLisandro Dalcin   }
11670598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
11680598e1a2SLisandro Dalcin }
11690598e1a2SLisandro Dalcin 
11700598e1a2SLisandro Dalcin static PetscErrorCode GmshReadElements(GmshFile *gmsh, GmshMesh *mesh)
11710598e1a2SLisandro Dalcin {
11720598e1a2SLisandro Dalcin   PetscFunctionBegin;
11730598e1a2SLisandro Dalcin   switch (gmsh->fileFormat) {
11745f80ce2aSJacob Faibussowitsch   case 41: CHKERRQ(GmshReadElements_v41(gmsh, mesh)); break;
11755f80ce2aSJacob Faibussowitsch   case 40: CHKERRQ(GmshReadElements_v40(gmsh, mesh)); break;
11765f80ce2aSJacob Faibussowitsch   default: CHKERRQ(GmshReadElements_v22(gmsh, mesh)); break;
11770598e1a2SLisandro Dalcin   }
11780598e1a2SLisandro Dalcin 
11790598e1a2SLisandro Dalcin   { /* Reorder elements by codimension and polytope type */
11800598e1a2SLisandro Dalcin     PetscInt    ne = mesh->numElems;
11810598e1a2SLisandro Dalcin     GmshElement *elements = mesh->elements;
1182066ea43fSLisandro Dalcin     PetscInt    keymap[GMSH_NUM_POLYTOPES], nk = 0;
1183066ea43fSLisandro Dalcin     PetscInt    offset[GMSH_NUM_POLYTOPES+1], e, k;
11840598e1a2SLisandro Dalcin 
1185066ea43fSLisandro Dalcin     for (k = 0; k < GMSH_NUM_POLYTOPES; ++k) keymap[k] = PETSC_MIN_INT;
11865f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMemzero(offset,sizeof(offset)));
11870598e1a2SLisandro Dalcin 
1188066ea43fSLisandro Dalcin     keymap[GMSH_TET] = nk++;
1189066ea43fSLisandro Dalcin     keymap[GMSH_HEX] = nk++;
1190066ea43fSLisandro Dalcin     keymap[GMSH_PRI] = nk++;
1191066ea43fSLisandro Dalcin     keymap[GMSH_PYR] = nk++;
1192066ea43fSLisandro Dalcin     keymap[GMSH_TRI] = nk++;
1193066ea43fSLisandro Dalcin     keymap[GMSH_QUA] = nk++;
1194066ea43fSLisandro Dalcin     keymap[GMSH_SEG] = nk++;
1195066ea43fSLisandro Dalcin     keymap[GMSH_VTX] = nk++;
11960598e1a2SLisandro Dalcin 
11975f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshElementsCreate(mesh->numElems, &mesh->elements));
11980598e1a2SLisandro Dalcin #define key(eid) keymap[GmshCellMap[elements[(eid)].cellType].polytope]
11990598e1a2SLisandro Dalcin     for (e = 0; e < ne; ++e) offset[1+key(e)]++;
12000598e1a2SLisandro Dalcin     for (k = 1; k < nk; ++k) offset[k] += offset[k-1];
12010598e1a2SLisandro Dalcin     for (e = 0; e < ne; ++e) mesh->elements[offset[key(e)]++] = elements[e];
12020598e1a2SLisandro Dalcin #undef key
12035f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshElementsDestroy(&elements));
1204066ea43fSLisandro Dalcin   }
12050598e1a2SLisandro Dalcin 
1206066ea43fSLisandro Dalcin   { /* Mesh dimension and order */
1207066ea43fSLisandro Dalcin     GmshElement *elem = mesh->numElems ? mesh->elements : NULL;
1208066ea43fSLisandro Dalcin     mesh->dim   = elem ? GmshCellMap[elem->cellType].dim   : 0;
1209066ea43fSLisandro Dalcin     mesh->order = elem ? GmshCellMap[elem->cellType].order : 0;
12100598e1a2SLisandro Dalcin   }
12110598e1a2SLisandro Dalcin 
12120598e1a2SLisandro Dalcin   {
12130598e1a2SLisandro Dalcin     PetscBT  vtx;
12140598e1a2SLisandro Dalcin     PetscInt dim = mesh->dim, e, n, v;
12150598e1a2SLisandro Dalcin 
12165f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscBTCreate(mesh->numNodes, &vtx));
12170598e1a2SLisandro Dalcin 
12180598e1a2SLisandro Dalcin     /* Compute number of cells and set of vertices */
12190598e1a2SLisandro Dalcin     mesh->numCells = 0;
12200598e1a2SLisandro Dalcin     for (e = 0; e < mesh->numElems; ++e) {
12210598e1a2SLisandro Dalcin       GmshElement *elem = mesh->elements + e;
12220598e1a2SLisandro Dalcin       if (elem->dim == dim && dim > 0) mesh->numCells++;
12230598e1a2SLisandro Dalcin       for (v = 0; v < elem->numVerts; v++) {
12245f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscBTSet(vtx, elem->nodes[v]));
12250598e1a2SLisandro Dalcin       }
12260598e1a2SLisandro Dalcin     }
12270598e1a2SLisandro Dalcin 
12280598e1a2SLisandro Dalcin     /* Compute numbering for vertices */
12290598e1a2SLisandro Dalcin     mesh->numVerts = 0;
12305f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(mesh->numNodes, &mesh->vertexMap));
12310598e1a2SLisandro Dalcin     for (n = 0; n < mesh->numNodes; ++n)
12320598e1a2SLisandro Dalcin       mesh->vertexMap[n] = PetscBTLookup(vtx, n) ? mesh->numVerts++ : PETSC_MIN_INT;
12330598e1a2SLisandro Dalcin 
12345f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscBTDestroy(&vtx));
12350598e1a2SLisandro Dalcin   }
12360598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
12370598e1a2SLisandro Dalcin }
12380598e1a2SLisandro Dalcin 
12390598e1a2SLisandro Dalcin static PetscErrorCode GmshReadPeriodic(GmshFile *gmsh, GmshMesh *mesh)
12400598e1a2SLisandro Dalcin {
12410598e1a2SLisandro Dalcin   PetscInt       n;
12420598e1a2SLisandro Dalcin 
12430598e1a2SLisandro Dalcin   PetscFunctionBegin;
12445f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(mesh->numNodes, &mesh->periodMap));
12450598e1a2SLisandro Dalcin   for (n = 0; n < mesh->numNodes; ++n) mesh->periodMap[n] = n;
12460598e1a2SLisandro Dalcin   switch (gmsh->fileFormat) {
12475f80ce2aSJacob Faibussowitsch   case 41: CHKERRQ(GmshReadPeriodic_v41(gmsh, mesh->periodMap)); break;
12485f80ce2aSJacob Faibussowitsch   default: CHKERRQ(GmshReadPeriodic_v40(gmsh, mesh->periodMap)); break;
12490598e1a2SLisandro Dalcin   }
12500598e1a2SLisandro Dalcin 
12519dddd249SSatish Balay   /* Find canonical primary nodes */
12520598e1a2SLisandro Dalcin   for (n = 0; n < mesh->numNodes; ++n)
12530598e1a2SLisandro Dalcin     while (mesh->periodMap[n] != mesh->periodMap[mesh->periodMap[n]])
12540598e1a2SLisandro Dalcin       mesh->periodMap[n] = mesh->periodMap[mesh->periodMap[n]];
12550598e1a2SLisandro Dalcin 
12569dddd249SSatish Balay   /* Renumber vertices (filter out correspondings) */
12570598e1a2SLisandro Dalcin   mesh->numVerts = 0;
12580598e1a2SLisandro Dalcin   for (n = 0; n < mesh->numNodes; ++n)
12590598e1a2SLisandro Dalcin     if (mesh->vertexMap[n] >= 0)   /* is vertex */
12609dddd249SSatish Balay       if (mesh->periodMap[n] == n) /* is primary */
12610598e1a2SLisandro Dalcin         mesh->vertexMap[n] = mesh->numVerts++;
12620598e1a2SLisandro Dalcin   for (n = 0; n < mesh->numNodes; ++n)
12630598e1a2SLisandro Dalcin     if (mesh->vertexMap[n] >= 0)   /* is vertex */
12649dddd249SSatish Balay       if (mesh->periodMap[n] != n) /* is corresponding  */
12650598e1a2SLisandro Dalcin         mesh->vertexMap[n] = mesh->vertexMap[mesh->periodMap[n]];
12660598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
12670598e1a2SLisandro Dalcin }
12680598e1a2SLisandro Dalcin 
1269066ea43fSLisandro Dalcin #define DM_POLYTOPE_VERTEX  DM_POLYTOPE_POINT
1270066ea43fSLisandro Dalcin #define DM_POLYTOPE_PYRAMID DM_POLYTOPE_UNKNOWN
1271066ea43fSLisandro Dalcin static const DMPolytopeType DMPolytopeMap[] = {
1272066ea43fSLisandro Dalcin   /* GMSH_VTX */ DM_POLYTOPE_VERTEX,
1273066ea43fSLisandro Dalcin   /* GMSH_SEG */ DM_POLYTOPE_SEGMENT,
1274066ea43fSLisandro Dalcin   /* GMSH_TRI */ DM_POLYTOPE_TRIANGLE,
1275066ea43fSLisandro Dalcin   /* GMSH_QUA */ DM_POLYTOPE_QUADRILATERAL,
1276066ea43fSLisandro Dalcin   /* GMSH_TET */ DM_POLYTOPE_TETRAHEDRON,
1277066ea43fSLisandro Dalcin   /* GMSH_HEX */ DM_POLYTOPE_HEXAHEDRON,
1278066ea43fSLisandro Dalcin   /* GMSH_PRI */ DM_POLYTOPE_TRI_PRISM,
1279066ea43fSLisandro Dalcin   /* GMSH_PYR */ DM_POLYTOPE_PYRAMID,
1280066ea43fSLisandro Dalcin   DM_POLYTOPE_UNKNOWN
1281066ea43fSLisandro Dalcin };
12820598e1a2SLisandro Dalcin 
12839fbee547SJacob Faibussowitsch static inline DMPolytopeType DMPolytopeTypeFromGmsh(PetscInt cellType)
12840598e1a2SLisandro Dalcin {
1285066ea43fSLisandro Dalcin   return DMPolytopeMap[GmshCellMap[cellType].polytope];
1286066ea43fSLisandro Dalcin }
1287066ea43fSLisandro Dalcin 
1288066ea43fSLisandro Dalcin static PetscErrorCode GmshCreateFE(MPI_Comm comm, const char prefix[], PetscBool isSimplex, PetscBool continuity, PetscDTNodeType nodeType, PetscInt dim, PetscInt Nc, PetscInt k, PetscFE *fem)
1289066ea43fSLisandro Dalcin {
1290066ea43fSLisandro Dalcin   DM              K;
1291066ea43fSLisandro Dalcin   PetscSpace      P;
1292066ea43fSLisandro Dalcin   PetscDualSpace  Q;
1293066ea43fSLisandro Dalcin   PetscQuadrature q, fq;
1294066ea43fSLisandro Dalcin   PetscBool       isTensor = isSimplex ? PETSC_FALSE : PETSC_TRUE;
1295066ea43fSLisandro Dalcin   PetscBool       endpoint = PETSC_TRUE;
1296066ea43fSLisandro Dalcin   char            name[32];
1297066ea43fSLisandro Dalcin 
1298066ea43fSLisandro Dalcin   PetscFunctionBegin;
1299066ea43fSLisandro Dalcin   /* Create space */
13005f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSpaceCreate(comm, &P));
13015f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSpaceSetType(P, PETSCSPACEPOLYNOMIAL));
13025f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSpacePolynomialSetTensor(P, isTensor));
13035f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSpaceSetNumComponents(P, Nc));
13045f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSpaceSetNumVariables(P, dim));
13055f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSpaceSetDegree(P, k, PETSC_DETERMINE));
1306066ea43fSLisandro Dalcin   if (prefix) {
13075f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject) P, prefix));
13085f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSpaceSetFromOptions(P));
13095f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject) P, NULL));
13105f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSpaceGetDegree(P, &k, NULL));
1311066ea43fSLisandro Dalcin   }
13125f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSpaceSetUp(P));
1313066ea43fSLisandro Dalcin   /* Create dual space */
13145f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscDualSpaceCreate(comm, &Q));
13155f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscDualSpaceSetType(Q, PETSCDUALSPACELAGRANGE));
13165f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscDualSpaceLagrangeSetTensor(Q, isTensor));
13175f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscDualSpaceLagrangeSetContinuity(Q, continuity));
13185f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscDualSpaceLagrangeSetNodeType(Q, nodeType, endpoint, 0));
13195f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscDualSpaceSetNumComponents(Q, Nc));
13205f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscDualSpaceSetOrder(Q, k));
13215f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCreateReferenceCell(PETSC_COMM_SELF, DMPolytopeTypeSimpleShape(dim, isSimplex), &K));
13225f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscDualSpaceSetDM(Q, K));
13235f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDestroy(&K));
1324066ea43fSLisandro Dalcin   if (prefix) {
13255f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject) Q, prefix));
13265f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscDualSpaceSetFromOptions(Q));
13275f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject) Q, NULL));
1328066ea43fSLisandro Dalcin   }
13295f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscDualSpaceSetUp(Q));
1330066ea43fSLisandro Dalcin   /* Create quadrature */
1331066ea43fSLisandro Dalcin   if (isSimplex) {
13325f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscDTStroudConicalQuadrature(dim,   1, k+1, -1, +1, &q));
13335f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscDTStroudConicalQuadrature(dim-1, 1, k+1, -1, +1, &fq));
1334066ea43fSLisandro Dalcin   } else {
13355f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscDTGaussTensorQuadrature(dim,   1, k+1, -1, +1, &q));
13365f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscDTGaussTensorQuadrature(dim-1, 1, k+1, -1, +1, &fq));
1337066ea43fSLisandro Dalcin   }
1338066ea43fSLisandro Dalcin   /* Create finite element */
13395f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFECreate(comm, fem));
13405f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFESetType(*fem, PETSCFEBASIC));
13415f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFESetNumComponents(*fem, Nc));
13425f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFESetBasisSpace(*fem, P));
13435f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFESetDualSpace(*fem, Q));
13445f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFESetQuadrature(*fem, q));
13455f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFESetFaceQuadrature(*fem, fq));
1346066ea43fSLisandro Dalcin   if (prefix) {
13475f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject) *fem, prefix));
13485f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFESetFromOptions(*fem));
13495f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject) *fem, NULL));
1350066ea43fSLisandro Dalcin   }
13515f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFESetUp(*fem));
1352066ea43fSLisandro Dalcin   /* Cleanup */
13535f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSpaceDestroy(&P));
13545f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscDualSpaceDestroy(&Q));
13555f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscQuadratureDestroy(&q));
13565f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscQuadratureDestroy(&fq));
1357066ea43fSLisandro Dalcin   /* Set finite element name */
13585f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSNPrintf(name, sizeof(name), "%s%D", isSimplex? "P" : "Q", k));
13595f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFESetName(*fem, name));
1360066ea43fSLisandro Dalcin   PetscFunctionReturn(0);
136196ca5757SLisandro Dalcin }
136296ca5757SLisandro Dalcin 
1363d6689ca9SLisandro Dalcin /*@C
1364d6689ca9SLisandro Dalcin   DMPlexCreateGmshFromFile - Create a DMPlex mesh from a Gmsh file
1365d6689ca9SLisandro Dalcin 
1366d6689ca9SLisandro Dalcin + comm        - The MPI communicator
1367d6689ca9SLisandro Dalcin . filename    - Name of the Gmsh file
1368d6689ca9SLisandro Dalcin - interpolate - Create faces and edges in the mesh
1369d6689ca9SLisandro Dalcin 
1370d6689ca9SLisandro Dalcin   Output Parameter:
1371d6689ca9SLisandro Dalcin . dm  - The DM object representing the mesh
1372d6689ca9SLisandro Dalcin 
1373d6689ca9SLisandro Dalcin   Level: beginner
1374d6689ca9SLisandro Dalcin 
1375d6689ca9SLisandro Dalcin .seealso: DMPlexCreateFromFile(), DMPlexCreateGmsh(), DMPlexCreate()
1376d6689ca9SLisandro Dalcin @*/
1377d6689ca9SLisandro Dalcin PetscErrorCode DMPlexCreateGmshFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm)
1378d6689ca9SLisandro Dalcin {
1379d6689ca9SLisandro Dalcin   PetscViewer     viewer;
1380d6689ca9SLisandro Dalcin   PetscMPIInt     rank;
1381d6689ca9SLisandro Dalcin   int             fileType;
1382d6689ca9SLisandro Dalcin   PetscViewerType vtype;
1383d6689ca9SLisandro Dalcin 
1384d6689ca9SLisandro Dalcin   PetscFunctionBegin;
13855f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm, &rank));
1386d6689ca9SLisandro Dalcin 
1387d6689ca9SLisandro Dalcin   /* Determine Gmsh file type (ASCII or binary) from file header */
1388dd400576SPatrick Sanan   if (rank == 0) {
13890598e1a2SLisandro Dalcin     GmshFile    gmsh[1];
1390d6689ca9SLisandro Dalcin     char        line[PETSC_MAX_PATH_LEN];
1391d6689ca9SLisandro Dalcin     int         snum;
1392d6689ca9SLisandro Dalcin     float       version;
1393d6689ca9SLisandro Dalcin 
13945f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArrayzero(gmsh,1));
13955f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerCreate(PETSC_COMM_SELF, &gmsh->viewer));
13965f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerSetType(gmsh->viewer, PETSCVIEWERASCII));
13975f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerFileSetMode(gmsh->viewer, FILE_MODE_READ));
13985f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerFileSetName(gmsh->viewer, filename));
1399d6689ca9SLisandro Dalcin     /* Read only the first two lines of the Gmsh file */
14005f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshReadSection(gmsh, line));
14015f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshExpect(gmsh, "$MeshFormat", line));
14025f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshReadString(gmsh, line, 2));
1403d6689ca9SLisandro Dalcin     snum = sscanf(line, "%f %d", &version, &fileType);
14042c71b3e2SJacob Faibussowitsch     PetscCheckFalse(snum != 2,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line);
14052c71b3e2SJacob Faibussowitsch     PetscCheckFalse(version < 2.2,PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at least 2.2", (double)version);
14062c71b3e2SJacob Faibussowitsch     PetscCheckFalse((int)version == 3,PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f not supported", (double)version);
14072c71b3e2SJacob Faibussowitsch     PetscCheckFalse(version > 4.1,PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at most 4.1", (double)version);
14085f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerDestroy(&gmsh->viewer));
1409d6689ca9SLisandro Dalcin   }
14105f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Bcast(&fileType, 1, MPI_INT, 0, comm));
1411d6689ca9SLisandro Dalcin   vtype = (fileType == 0) ? PETSCVIEWERASCII : PETSCVIEWERBINARY;
1412d6689ca9SLisandro Dalcin 
1413d6689ca9SLisandro Dalcin   /* Create appropriate viewer and build plex */
14145f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerCreate(comm, &viewer));
14155f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerSetType(viewer, vtype));
14165f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
14175f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerFileSetName(viewer, filename));
14185f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCreateGmsh(comm, viewer, interpolate, dm));
14195f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerDestroy(&viewer));
1420d6689ca9SLisandro Dalcin   PetscFunctionReturn(0);
1421d6689ca9SLisandro Dalcin }
1422d6689ca9SLisandro Dalcin 
1423331830f3SMatthew G. Knepley /*@
14247d282ae0SMichael Lange   DMPlexCreateGmsh - Create a DMPlex mesh from a Gmsh file viewer
1425331830f3SMatthew G. Knepley 
1426d083f849SBarry Smith   Collective
1427331830f3SMatthew G. Knepley 
1428331830f3SMatthew G. Knepley   Input Parameters:
1429331830f3SMatthew G. Knepley + comm  - The MPI communicator
1430331830f3SMatthew G. Knepley . viewer - The Viewer associated with a Gmsh file
1431331830f3SMatthew G. Knepley - interpolate - Create faces and edges in the mesh
1432331830f3SMatthew G. Knepley 
1433331830f3SMatthew G. Knepley   Output Parameter:
1434331830f3SMatthew G. Knepley . dm  - The DM object representing the mesh
1435331830f3SMatthew G. Knepley 
1436698a79b9SLisandro Dalcin   Note: http://gmsh.info/doc/texinfo/gmsh.html#MSH-file-format
1437331830f3SMatthew G. Knepley 
1438331830f3SMatthew G. Knepley   Level: beginner
1439331830f3SMatthew G. Knepley 
1440331830f3SMatthew G. Knepley .seealso: DMPLEX, DMCreate()
1441331830f3SMatthew G. Knepley @*/
1442331830f3SMatthew G. Knepley PetscErrorCode DMPlexCreateGmsh(MPI_Comm comm, PetscViewer viewer, PetscBool interpolate, DM *dm)
1443331830f3SMatthew G. Knepley {
14440598e1a2SLisandro Dalcin   GmshMesh      *mesh = NULL;
144511c56cb0SLisandro Dalcin   PetscViewer    parentviewer = NULL;
14460598e1a2SLisandro Dalcin   PetscBT        periodicVerts = NULL;
14470598e1a2SLisandro Dalcin   PetscBT        periodicCells = NULL;
1448066ea43fSLisandro Dalcin   DM             cdm;
1449331830f3SMatthew G. Knepley   PetscSection   coordSection;
1450331830f3SMatthew G. Knepley   Vec            coordinates;
1451a45dabc8SMatthew G. Knepley   DMLabel        cellSets = NULL, faceSets = NULL, vertSets = NULL, marker = NULL, *regionSets;
1452066ea43fSLisandro Dalcin   PetscInt       dim = 0, coordDim = -1, order = 0;
14530598e1a2SLisandro Dalcin   PetscInt       numNodes = 0, numElems = 0, numVerts = 0, numCells = 0;
1454066ea43fSLisandro Dalcin   PetscInt       cell, cone[8], e, n, v, d;
145581a1af93SMatthew G. Knepley   PetscBool      binary, usemarker = PETSC_FALSE, useregions = PETSC_FALSE, markvertices = PETSC_FALSE;
14560598e1a2SLisandro Dalcin   PetscBool      hybrid = interpolate, periodic = PETSC_TRUE;
1457066ea43fSLisandro Dalcin   PetscBool      highOrder = PETSC_TRUE, highOrderSet, project = PETSC_FALSE;
1458066ea43fSLisandro Dalcin   PetscBool      isSimplex = PETSC_FALSE, isHybrid = PETSC_FALSE, hasTetra = PETSC_FALSE;
14590598e1a2SLisandro Dalcin   PetscMPIInt    rank;
1460331830f3SMatthew G. Knepley   PetscErrorCode ierr;
1461331830f3SMatthew G. Knepley 
1462331830f3SMatthew G. Knepley   PetscFunctionBegin;
14635f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm, &rank));
1464ef12879bSLisandro Dalcin   ierr = PetscObjectOptionsBegin((PetscObject)viewer);CHKERRQ(ierr);
14655f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsHead(PetscOptionsObject,"DMPlex Gmsh options"));
14665f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-dm_plex_gmsh_hybrid", "Generate hybrid cell bounds", "DMPlexCreateGmsh", hybrid, &hybrid, NULL));
14675f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-dm_plex_gmsh_periodic","Read Gmsh periodic section", "DMPlexCreateGmsh", periodic, &periodic, NULL));
14685f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-dm_plex_gmsh_highorder","Generate high-order coordinates", "DMPlexCreateGmsh", highOrder, &highOrder, &highOrderSet));
14695f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-dm_plex_gmsh_project", "Project high-order coordinates to a different space", "DMPlexCreateGmsh", project, &project, NULL));
14705f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-dm_plex_gmsh_use_marker", "Generate marker label", "DMPlexCreateGmsh", usemarker, &usemarker, NULL));
14715f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-dm_plex_gmsh_use_regions", "Generate labels with region names", "DMPlexCreateGmsh", useregions, &useregions, NULL));
14725f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-dm_plex_gmsh_mark_vertices", "Add vertices to generated labels", "DMPlexCreateGmsh", markvertices, &markvertices, NULL));
14735f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBoundedInt("-dm_plex_gmsh_spacedim", "Embedding space dimension", "DMPlexCreateGmsh", coordDim, &coordDim, NULL, PETSC_DECIDE));
14745f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsTail());
1475ef12879bSLisandro Dalcin   ierr = PetscOptionsEnd();CHKERRQ(ierr);
14760598e1a2SLisandro Dalcin 
14775f80ce2aSJacob Faibussowitsch   CHKERRQ(GmshCellInfoSetUp());
147811c56cb0SLisandro Dalcin 
14795f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreate(comm, dm));
14805f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetType(*dm, DMPLEX));
14815f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_CreateGmsh,*dm,NULL,NULL,NULL));
148211c56cb0SLisandro Dalcin 
14835f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &binary));
148411c56cb0SLisandro Dalcin 
148511c56cb0SLisandro Dalcin   /* Binary viewers read on all ranks, get subviewer to read only in rank 0 */
14863b46f529SLisandro Dalcin   if (binary) {
148711c56cb0SLisandro Dalcin     parentviewer = viewer;
14885f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerGetSubViewer(parentviewer, PETSC_COMM_SELF, &viewer));
148911c56cb0SLisandro Dalcin   }
149011c56cb0SLisandro Dalcin 
1491dd400576SPatrick Sanan   if (rank == 0) {
14920598e1a2SLisandro Dalcin     GmshFile  gmsh[1];
1493698a79b9SLisandro Dalcin     char      line[PETSC_MAX_PATH_LEN];
1494698a79b9SLisandro Dalcin     PetscBool match;
1495331830f3SMatthew G. Knepley 
14965f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArrayzero(gmsh,1));
1497698a79b9SLisandro Dalcin     gmsh->viewer = viewer;
1498698a79b9SLisandro Dalcin     gmsh->binary = binary;
1499698a79b9SLisandro Dalcin 
15005f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshMeshCreate(&mesh));
15010598e1a2SLisandro Dalcin 
1502698a79b9SLisandro Dalcin     /* Read mesh format */
15035f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshReadSection(gmsh, line));
15045f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshExpect(gmsh, "$MeshFormat", line));
15055f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshReadMeshFormat(gmsh));
15065f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshReadEndSection(gmsh, "$EndMeshFormat", line));
150711c56cb0SLisandro Dalcin 
1508dc0ede3bSMatthew G. Knepley     /* OPTIONAL Read physical names */
15095f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshReadSection(gmsh, line));
15105f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshMatch(gmsh, "$PhysicalNames", line, &match));
1511dc0ede3bSMatthew G. Knepley     if (match) {
15125f80ce2aSJacob Faibussowitsch       CHKERRQ(GmshExpect(gmsh, "$PhysicalNames", line));
15135f80ce2aSJacob Faibussowitsch       CHKERRQ(GmshReadPhysicalNames(gmsh, mesh));
15145f80ce2aSJacob Faibussowitsch       CHKERRQ(GmshReadEndSection(gmsh, "$EndPhysicalNames", line));
1515698a79b9SLisandro Dalcin       /* Initial read for entity section */
15165f80ce2aSJacob Faibussowitsch       CHKERRQ(GmshReadSection(gmsh, line));
1517dc0ede3bSMatthew G. Knepley     }
151811c56cb0SLisandro Dalcin 
1519de78e4feSLisandro Dalcin     /* Read entities */
1520698a79b9SLisandro Dalcin     if (gmsh->fileFormat >= 40) {
15215f80ce2aSJacob Faibussowitsch       CHKERRQ(GmshExpect(gmsh, "$Entities", line));
15225f80ce2aSJacob Faibussowitsch       CHKERRQ(GmshReadEntities(gmsh, mesh));
15235f80ce2aSJacob Faibussowitsch       CHKERRQ(GmshReadEndSection(gmsh, "$EndEntities", line));
1524698a79b9SLisandro Dalcin       /* Initial read for nodes section */
15255f80ce2aSJacob Faibussowitsch       CHKERRQ(GmshReadSection(gmsh, line));
1526de78e4feSLisandro Dalcin     }
1527de78e4feSLisandro Dalcin 
1528698a79b9SLisandro Dalcin     /* Read nodes */
15295f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshExpect(gmsh, "$Nodes", line));
15305f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshReadNodes(gmsh, mesh));
15315f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshReadEndSection(gmsh, "$EndNodes", line));
153211c56cb0SLisandro Dalcin 
1533698a79b9SLisandro Dalcin     /* Read elements */
15345f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshReadSection(gmsh, line));
15355f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshExpect(gmsh, "$Elements", line));
15365f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshReadElements(gmsh, mesh));
15375f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshReadEndSection(gmsh, "$EndElements", line));
1538de78e4feSLisandro Dalcin 
15390598e1a2SLisandro Dalcin     /* Read periodic section (OPTIONAL) */
1540698a79b9SLisandro Dalcin     if (periodic) {
15415f80ce2aSJacob Faibussowitsch       CHKERRQ(GmshReadSection(gmsh, line));
15425f80ce2aSJacob Faibussowitsch       CHKERRQ(GmshMatch(gmsh, "$Periodic", line, &periodic));
1543ef12879bSLisandro Dalcin     }
1544ef12879bSLisandro Dalcin     if (periodic) {
15455f80ce2aSJacob Faibussowitsch       CHKERRQ(GmshExpect(gmsh, "$Periodic", line));
15465f80ce2aSJacob Faibussowitsch       CHKERRQ(GmshReadPeriodic(gmsh, mesh));
15475f80ce2aSJacob Faibussowitsch       CHKERRQ(GmshReadEndSection(gmsh, "$EndPeriodic", line));
1548698a79b9SLisandro Dalcin     }
1549698a79b9SLisandro Dalcin 
15505f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(gmsh->wbuf));
15515f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(gmsh->sbuf));
15525f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(gmsh->nbuf));
15530598e1a2SLisandro Dalcin 
15540598e1a2SLisandro Dalcin     dim       = mesh->dim;
1555066ea43fSLisandro Dalcin     order     = mesh->order;
15560598e1a2SLisandro Dalcin     numNodes  = mesh->numNodes;
15570598e1a2SLisandro Dalcin     numElems  = mesh->numElems;
15580598e1a2SLisandro Dalcin     numVerts  = mesh->numVerts;
15590598e1a2SLisandro Dalcin     numCells  = mesh->numCells;
1560066ea43fSLisandro Dalcin 
1561066ea43fSLisandro Dalcin     {
1562066ea43fSLisandro Dalcin       GmshElement *elemA = mesh->numCells > 0 ? mesh->elements : NULL;
1563066ea43fSLisandro Dalcin       GmshElement *elemB = elemA ? elemA + mesh->numCells - 1  : NULL;
1564066ea43fSLisandro Dalcin       int ptA = elemA ? GmshCellMap[elemA->cellType].polytope : -1;
1565066ea43fSLisandro Dalcin       int ptB = elemB ? GmshCellMap[elemB->cellType].polytope : -1;
1566066ea43fSLisandro Dalcin       isSimplex = (ptA == GMSH_QUA || ptA == GMSH_HEX) ? PETSC_FALSE : PETSC_TRUE;
1567066ea43fSLisandro Dalcin       isHybrid  = (ptA == ptB) ? PETSC_FALSE : PETSC_TRUE;
1568066ea43fSLisandro Dalcin       hasTetra  = (ptA == GMSH_TET) ? PETSC_TRUE : PETSC_FALSE;
1569066ea43fSLisandro Dalcin     }
1570698a79b9SLisandro Dalcin   }
1571698a79b9SLisandro Dalcin 
1572698a79b9SLisandro Dalcin   if (parentviewer) {
15735f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerRestoreSubViewer(parentviewer, PETSC_COMM_SELF, &viewer));
1574698a79b9SLisandro Dalcin   }
1575698a79b9SLisandro Dalcin 
1576066ea43fSLisandro Dalcin   {
1577066ea43fSLisandro Dalcin     int buf[6];
1578698a79b9SLisandro Dalcin 
1579066ea43fSLisandro Dalcin     buf[0] = (int)dim;
1580066ea43fSLisandro Dalcin     buf[1] = (int)order;
1581066ea43fSLisandro Dalcin     buf[2] = periodic;
1582066ea43fSLisandro Dalcin     buf[3] = isSimplex;
1583066ea43fSLisandro Dalcin     buf[4] = isHybrid;
1584066ea43fSLisandro Dalcin     buf[5] = hasTetra;
1585066ea43fSLisandro Dalcin 
15865f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Bcast(buf, 6, MPI_INT, 0, comm));
1587066ea43fSLisandro Dalcin 
1588066ea43fSLisandro Dalcin     dim       = buf[0];
1589066ea43fSLisandro Dalcin     order     = buf[1];
1590066ea43fSLisandro Dalcin     periodic  = buf[2] ? PETSC_TRUE : PETSC_FALSE;
1591066ea43fSLisandro Dalcin     isSimplex = buf[3] ? PETSC_TRUE : PETSC_FALSE;
1592066ea43fSLisandro Dalcin     isHybrid  = buf[4] ? PETSC_TRUE : PETSC_FALSE;
1593066ea43fSLisandro Dalcin     hasTetra  = buf[5] ? PETSC_TRUE : PETSC_FALSE;
1594dea2a3c7SStefano Zampini   }
1595dea2a3c7SStefano Zampini 
1596066ea43fSLisandro Dalcin   if (!highOrderSet) highOrder = (order > 1) ? PETSC_TRUE : PETSC_FALSE;
15972c71b3e2SJacob Faibussowitsch   PetscCheckFalse(highOrder && isHybrid,comm, PETSC_ERR_SUP, "No support for discretization on hybrid meshes yet");
1598066ea43fSLisandro Dalcin 
15990598e1a2SLisandro Dalcin   /* We do not want this label automatically computed, instead we fill it here */
16005f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateLabel(*dm, "celltype"));
160111c56cb0SLisandro Dalcin 
1602a4bb7517SMichael Lange   /* Allocate the cell-vertex mesh */
16035f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexSetChart(*dm, 0, numCells+numVerts));
16040598e1a2SLisandro Dalcin   for (cell = 0; cell < numCells; ++cell) {
16050598e1a2SLisandro Dalcin     GmshElement *elem = mesh->elements + cell;
16060598e1a2SLisandro Dalcin     DMPolytopeType ctype = DMPolytopeTypeFromGmsh(elem->cellType);
16070598e1a2SLisandro Dalcin     if (hybrid && hasTetra && ctype == DM_POLYTOPE_TRI_PRISM) ctype = DM_POLYTOPE_TRI_PRISM_TENSOR;
16085f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexSetConeSize(*dm, cell, elem->numVerts));
16095f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexSetCellType(*dm, cell, ctype));
1610db397164SMichael Lange   }
16110598e1a2SLisandro Dalcin   for (v = numCells; v < numCells+numVerts; ++v) {
16125f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexSetCellType(*dm, v, DM_POLYTOPE_POINT));
161396ca5757SLisandro Dalcin   }
16145f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetUp(*dm));
161596ca5757SLisandro Dalcin 
1616a4bb7517SMichael Lange   /* Add cell-vertex connections */
16170598e1a2SLisandro Dalcin   for (cell = 0; cell < numCells; ++cell) {
16180598e1a2SLisandro Dalcin     GmshElement *elem = mesh->elements + cell;
16190598e1a2SLisandro Dalcin     for (v = 0; v < elem->numVerts; ++v) {
16200598e1a2SLisandro Dalcin       const PetscInt nn = elem->nodes[v];
16210598e1a2SLisandro Dalcin       const PetscInt vv = mesh->vertexMap[nn];
16220598e1a2SLisandro Dalcin       cone[v] = numCells + vv;
1623db397164SMichael Lange     }
16245f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexReorderCell(*dm, cell, cone));
16255f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexSetCone(*dm, cell, cone));
1626a4bb7517SMichael Lange   }
162796ca5757SLisandro Dalcin 
16285f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetDimension(*dm, dim));
16295f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexSymmetrize(*dm));
16305f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexStratify(*dm));
1631331830f3SMatthew G. Knepley   if (interpolate) {
16325fd9971aSMatthew G. Knepley     DM idm;
1633331830f3SMatthew G. Knepley 
16345f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexInterpolate(*dm, &idm));
16355f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDestroy(dm));
1636331830f3SMatthew G. Knepley     *dm  = idm;
1637331830f3SMatthew G. Knepley   }
1638917266a4SLisandro Dalcin 
163981a1af93SMatthew G. Knepley   /* Create the label "marker" over the whole boundary */
16402c71b3e2SJacob Faibussowitsch   PetscCheckFalse(usemarker && !interpolate && dim > 1,comm,PETSC_ERR_SUP,"Cannot create marker label without interpolation");
1641dd400576SPatrick Sanan   if (rank == 0 && usemarker) {
1642d3f73514SStefano Zampini     PetscInt f, fStart, fEnd;
1643d3f73514SStefano Zampini 
16445f80ce2aSJacob Faibussowitsch     CHKERRQ(DMCreateLabel(*dm, "marker"));
16455f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetHeightStratum(*dm, 1, &fStart, &fEnd));
1646d3f73514SStefano Zampini     for (f = fStart; f < fEnd; ++f) {
1647d3f73514SStefano Zampini       PetscInt suppSize;
1648d3f73514SStefano Zampini 
16495f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetSupportSize(*dm, f, &suppSize));
1650d3f73514SStefano Zampini       if (suppSize == 1) {
1651d3f73514SStefano Zampini         PetscInt *cone = NULL, coneSize, p;
1652d3f73514SStefano Zampini 
16535f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetTransitiveClosure(*dm, f, PETSC_TRUE, &coneSize, &cone));
1654d3f73514SStefano Zampini         for (p = 0; p < coneSize; p += 2) {
16555f80ce2aSJacob Faibussowitsch           CHKERRQ(DMSetLabelValue_Fast(*dm, &marker, "marker", cone[p], 1));
1656d3f73514SStefano Zampini         }
16575f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexRestoreTransitiveClosure(*dm, f, PETSC_TRUE, &coneSize, &cone));
1658d3f73514SStefano Zampini       }
1659d3f73514SStefano Zampini     }
1660d3f73514SStefano Zampini   }
166116ad7e67SMichael Lange 
1662dd400576SPatrick Sanan   if (rank == 0) {
1663a45dabc8SMatthew G. Knepley     const PetscInt Nr = useregions ? mesh->numRegions : 0;
166411c56cb0SLisandro Dalcin     PetscInt       vStart, vEnd;
1665d1a54cefSMatthew G. Knepley 
16665f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscCalloc1(Nr, &regionSets));
16675f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetDepthStratum(*dm, 0, &vStart, &vEnd));
16680598e1a2SLisandro Dalcin     for (cell = 0, e = 0; e < numElems; ++e) {
16690598e1a2SLisandro Dalcin       GmshElement *elem = mesh->elements + e;
16706e1dd89aSLawrence Mitchell 
16716e1dd89aSLawrence Mitchell       /* Create cell sets */
16720598e1a2SLisandro Dalcin       if (elem->dim == dim && dim > 0) {
16730598e1a2SLisandro Dalcin         if (elem->numTags > 0) {
1674a45dabc8SMatthew G. Knepley           const PetscInt tag = elem->tags[0];
1675a45dabc8SMatthew G. Knepley           PetscInt       r;
1676a45dabc8SMatthew G. Knepley 
16775f80ce2aSJacob Faibussowitsch           if (!Nr) CHKERRQ(DMSetLabelValue_Fast(*dm, &cellSets, "Cell Sets", cell, tag));
1678a45dabc8SMatthew G. Knepley           for (r = 0; r < Nr; ++r) {
16795f80ce2aSJacob Faibussowitsch             if (mesh->regionTags[r] == tag) CHKERRQ(DMSetLabelValue_Fast(*dm, &regionSets[r], mesh->regionNames[r], cell, tag));
1680a45dabc8SMatthew G. Knepley           }
16816e1dd89aSLawrence Mitchell         }
1682917266a4SLisandro Dalcin         cell++;
16836e1dd89aSLawrence Mitchell       }
16840c070f12SSander Arens 
16850598e1a2SLisandro Dalcin       /* Create face sets */
16860598e1a2SLisandro Dalcin       if (interpolate && elem->dim == dim-1) {
16870598e1a2SLisandro Dalcin         PetscInt        joinSize;
16880598e1a2SLisandro Dalcin         const PetscInt *join = NULL;
1689a45dabc8SMatthew G. Knepley         const PetscInt  tag = elem->tags[0];
1690a45dabc8SMatthew G. Knepley         PetscInt        r;
1691a45dabc8SMatthew G. Knepley 
16920598e1a2SLisandro Dalcin         /* Find the relevant facet with vertex joins */
16930598e1a2SLisandro Dalcin         for (v = 0; v < elem->numVerts; ++v) {
16940598e1a2SLisandro Dalcin           const PetscInt nn = elem->nodes[v];
16950598e1a2SLisandro Dalcin           const PetscInt vv = mesh->vertexMap[nn];
16960598e1a2SLisandro Dalcin           cone[v] = vStart + vv;
16970598e1a2SLisandro Dalcin         }
16985f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetFullJoin(*dm, elem->numVerts, cone, &joinSize, &join));
16992c71b3e2SJacob 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);
17005f80ce2aSJacob Faibussowitsch         if (!Nr) CHKERRQ(DMSetLabelValue_Fast(*dm, &faceSets, "Face Sets", join[0], tag));
1701a45dabc8SMatthew G. Knepley         for (r = 0; r < Nr; ++r) {
17025f80ce2aSJacob Faibussowitsch           if (mesh->regionTags[r] == tag) CHKERRQ(DMSetLabelValue_Fast(*dm, &regionSets[r], mesh->regionNames[r], join[0], tag));
1703a45dabc8SMatthew G. Knepley         }
17045f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexRestoreJoin(*dm, elem->numVerts, cone, &joinSize, &join));
17050598e1a2SLisandro Dalcin       }
17060598e1a2SLisandro Dalcin 
17070c070f12SSander Arens       /* Create vertex sets */
17080598e1a2SLisandro Dalcin       if (elem->dim == 0) {
17090598e1a2SLisandro Dalcin         if (elem->numTags > 0) {
17100598e1a2SLisandro Dalcin           const PetscInt nn = elem->nodes[0];
17110598e1a2SLisandro Dalcin           const PetscInt vv = mesh->vertexMap[nn];
1712a45dabc8SMatthew G. Knepley           const PetscInt tag = elem->tags[0];
1713a45dabc8SMatthew G. Knepley           PetscInt       r;
1714a45dabc8SMatthew G. Knepley 
17155f80ce2aSJacob Faibussowitsch           if (!Nr) CHKERRQ(DMSetLabelValue_Fast(*dm, &vertSets, "Vertex Sets", vStart + vv, tag));
171681a1af93SMatthew G. Knepley           for (r = 0; r < Nr; ++r) {
17175f80ce2aSJacob Faibussowitsch             if (mesh->regionTags[r] == tag) CHKERRQ(DMSetLabelValue_Fast(*dm, &regionSets[r], mesh->regionNames[r], vStart + vv, tag));
171881a1af93SMatthew G. Knepley           }
171981a1af93SMatthew G. Knepley         }
172081a1af93SMatthew G. Knepley       }
172181a1af93SMatthew G. Knepley     }
172281a1af93SMatthew G. Knepley     if (markvertices) {
172381a1af93SMatthew G. Knepley       for (v = 0; v < numNodes; ++v) {
172481a1af93SMatthew G. Knepley         const PetscInt vv  = mesh->vertexMap[v];
172581a1af93SMatthew G. Knepley         const PetscInt tag = mesh->nodelist->tag[v];
172681a1af93SMatthew G. Knepley         PetscInt       r;
172781a1af93SMatthew G. Knepley 
172881a1af93SMatthew G. Knepley         if (tag != -1) {
17295f80ce2aSJacob Faibussowitsch           if (!Nr) CHKERRQ(DMSetLabelValue_Fast(*dm, &vertSets, "Vertex Sets", vStart + vv, tag));
1730a45dabc8SMatthew G. Knepley           for (r = 0; r < Nr; ++r) {
17315f80ce2aSJacob Faibussowitsch             if (mesh->regionTags[r] == tag) CHKERRQ(DMSetLabelValue_Fast(*dm, &regionSets[r], mesh->regionNames[r], vStart + vv, tag));
17320598e1a2SLisandro Dalcin           }
17330598e1a2SLisandro Dalcin         }
17340598e1a2SLisandro Dalcin       }
17350598e1a2SLisandro Dalcin     }
17365f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(regionSets));
1737a45dabc8SMatthew G. Knepley   }
17380598e1a2SLisandro Dalcin 
17397dd454faSLisandro Dalcin   { /* Create Cell/Face/Vertex Sets labels at all processes */
17407dd454faSLisandro Dalcin     enum {n = 4};
17417dd454faSLisandro Dalcin     PetscBool flag[n];
17427dd454faSLisandro Dalcin 
17437dd454faSLisandro Dalcin     flag[0] = cellSets ? PETSC_TRUE : PETSC_FALSE;
17447dd454faSLisandro Dalcin     flag[1] = faceSets ? PETSC_TRUE : PETSC_FALSE;
17457dd454faSLisandro Dalcin     flag[2] = vertSets ? PETSC_TRUE : PETSC_FALSE;
17467dd454faSLisandro Dalcin     flag[3] = marker   ? PETSC_TRUE : PETSC_FALSE;
17475f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Bcast(flag, n, MPIU_BOOL, 0, comm));
17485f80ce2aSJacob Faibussowitsch     if (flag[0]) CHKERRQ(DMCreateLabel(*dm, "Cell Sets"));
17495f80ce2aSJacob Faibussowitsch     if (flag[1]) CHKERRQ(DMCreateLabel(*dm, "Face Sets"));
17505f80ce2aSJacob Faibussowitsch     if (flag[2]) CHKERRQ(DMCreateLabel(*dm, "Vertex Sets"));
17515f80ce2aSJacob Faibussowitsch     if (flag[3]) CHKERRQ(DMCreateLabel(*dm, "marker"));
17527dd454faSLisandro Dalcin   }
17537dd454faSLisandro Dalcin 
17540598e1a2SLisandro Dalcin   if (periodic) {
17555f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscBTCreate(numVerts, &periodicVerts));
17560598e1a2SLisandro Dalcin     for (n = 0; n < numNodes; ++n) {
17570598e1a2SLisandro Dalcin       if (mesh->vertexMap[n] >= 0) {
17580598e1a2SLisandro Dalcin         if (PetscUnlikely(mesh->periodMap[n] != n)) {
17590598e1a2SLisandro Dalcin           PetscInt m = mesh->periodMap[n];
17605f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscBTSet(periodicVerts, mesh->vertexMap[n]));
17615f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscBTSet(periodicVerts, mesh->vertexMap[m]));
17620598e1a2SLisandro Dalcin         }
17630598e1a2SLisandro Dalcin       }
17640598e1a2SLisandro Dalcin     }
17655f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscBTCreate(numCells, &periodicCells));
17660598e1a2SLisandro Dalcin     for (cell = 0; cell < numCells; ++cell) {
17670598e1a2SLisandro Dalcin       GmshElement *elem = mesh->elements + cell;
17680598e1a2SLisandro Dalcin       for (v = 0; v < elem->numVerts; ++v) {
17690598e1a2SLisandro Dalcin         PetscInt nn = elem->nodes[v];
17700598e1a2SLisandro Dalcin         PetscInt vv = mesh->vertexMap[nn];
17710598e1a2SLisandro Dalcin         if (PetscUnlikely(PetscBTLookup(periodicVerts, vv))) {
17725f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscBTSet(periodicCells, cell)); break;
17730c070f12SSander Arens         }
17740c070f12SSander Arens       }
17750c070f12SSander Arens     }
177616ad7e67SMichael Lange   }
177716ad7e67SMichael Lange 
1778066ea43fSLisandro Dalcin   /* Setup coordinate DM */
17790598e1a2SLisandro Dalcin   if (coordDim < 0) coordDim = dim;
17805f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetCoordinateDim(*dm, coordDim));
17815f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateDM(*dm, &cdm));
1782066ea43fSLisandro Dalcin   if (highOrder) {
1783066ea43fSLisandro Dalcin     PetscFE         fe;
1784066ea43fSLisandro Dalcin     PetscBool       continuity = periodic ? PETSC_FALSE : PETSC_TRUE;
1785066ea43fSLisandro Dalcin     PetscDTNodeType nodeType   = PETSCDTNODES_EQUISPACED;
1786066ea43fSLisandro Dalcin 
1787066ea43fSLisandro Dalcin     if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */
1788066ea43fSLisandro Dalcin 
17895f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshCreateFE(comm, NULL, isSimplex, continuity, nodeType, dim, coordDim, order, &fe));
17905f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_fe_view"));
17915f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetField(cdm, 0, NULL, (PetscObject) fe));
17925f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFEDestroy(&fe));
17935f80ce2aSJacob Faibussowitsch     CHKERRQ(DMCreateDS(cdm));
1794066ea43fSLisandro Dalcin   }
1795066ea43fSLisandro Dalcin 
1796066ea43fSLisandro Dalcin   /* Create coordinates */
1797066ea43fSLisandro Dalcin   if (highOrder) {
1798066ea43fSLisandro Dalcin 
1799066ea43fSLisandro Dalcin     PetscInt     maxDof = GmshNumNodes_HEX(order)*coordDim;
1800066ea43fSLisandro Dalcin     double       *coords = mesh ? mesh->nodelist->xyz : NULL;
1801066ea43fSLisandro Dalcin     PetscSection section;
1802066ea43fSLisandro Dalcin     PetscScalar  *cellCoords;
1803066ea43fSLisandro Dalcin 
18045f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetLocalSection(cdm, NULL));
18055f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetLocalSection(cdm, &coordSection));
18065f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionClone(coordSection, &section));
18075f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexSetClosurePermutationTensor(cdm, 0, section)); /* XXX Implement DMPlexSetClosurePermutationLexicographic() */
1808066ea43fSLisandro Dalcin 
18095f80ce2aSJacob Faibussowitsch     CHKERRQ(DMCreateLocalVector(cdm, &coordinates));
18105f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(maxDof, &cellCoords));
1811066ea43fSLisandro Dalcin     for (cell = 0; cell < numCells; ++cell) {
1812066ea43fSLisandro Dalcin       GmshElement *elem = mesh->elements + cell;
1813066ea43fSLisandro Dalcin       const int *lexorder = GmshCellMap[elem->cellType].lexorder();
1814b9bf55e5SMatthew G. Knepley       int s = 0;
1815066ea43fSLisandro Dalcin       for (n = 0; n < elem->numNodes; ++n) {
1816b9bf55e5SMatthew G. Knepley         while (lexorder[n+s] < 0) ++s;
1817b9bf55e5SMatthew G. Knepley         const PetscInt node = elem->nodes[lexorder[n+s]];
1818b9bf55e5SMatthew G. Knepley         for (d = 0; d < coordDim; ++d) cellCoords[(n+s)*coordDim+d] = (PetscReal) coords[node*3+d];
1819b9bf55e5SMatthew G. Knepley       }
1820b9bf55e5SMatthew G. Knepley       if (s) {
1821b9bf55e5SMatthew G. Knepley         /* For the coordinate mapping we weight vertices by -1/4 and edges by 1/2, which we get from Q_2 interpolation */
1822b9bf55e5SMatthew G. Knepley         PetscReal quaCenterWeights[9]  = {-0.25, 0.5, -0.25, 0.5, 0.0, 0.5, -0.25, 0.5, -0.25};
1823b9bf55e5SMatthew G. Knepley         /* For the coordinate mapping we weight vertices by -1/4 and edges by 1/2, which we get from Q_2 interpolation */
1824b9bf55e5SMatthew G. Knepley         PetscReal hexBottomWeights[27] = {-0.25, 0.5,  -0.25, 0.5,  0.0, 0.5,  -0.25, 0.5,  -0.25,
1825b9bf55e5SMatthew G. Knepley                                            0.0,  0.0,   0.0,  0.0,  0.0, 0.0,   0.0,  0.0,   0.0,
1826b9bf55e5SMatthew G. Knepley                                            0.0,  0.0,   0.0,  0.0,  0.0, 0.0,   0.0,  0.0,   0.0};
1827b9bf55e5SMatthew G. Knepley         PetscReal hexFrontWeights[27]  = {-0.25, 0.5,  -0.25, 0.0,  0.0, 0.0,   0.0,  0.0,   0.0,
1828b9bf55e5SMatthew G. Knepley                                            0.5,  0.0,   0.5,  0.0,  0.0, 0.0,   0.0,  0.0,   0.0,
1829b9bf55e5SMatthew G. Knepley                                           -0.25, 0.5,  -0.25, 0.0,  0.0, 0.0,   0.0,  0.0,   0.0};
1830b9bf55e5SMatthew G. Knepley         PetscReal hexLeftWeights[27]   = {-0.25, 0.0,   0.0,  0.5,  0.0, 0.0,  -0.25, 0.0,   0.0,
1831b9bf55e5SMatthew G. Knepley                                            0.5,  0.0,   0.0,  0.0,  0.0, 0.0,   0.5,  0.0,   0.0,
1832b9bf55e5SMatthew G. Knepley                                           -0.25, 0.0,   0.0,  0.5,  0.0, 0.0,  -0.25, 0.0,   0.0};
1833b9bf55e5SMatthew G. Knepley         PetscReal hexRightWeights[27]  = { 0.0,  0.0,  -0.25, 0.0,  0.0, 0.5,   0.0,  0.0,  -0.25,
1834b9bf55e5SMatthew G. Knepley                                            0.0,  0.0,   0.5,  0.0,  0.0, 0.0,   0.0,  0.0,   0.5,
1835b9bf55e5SMatthew G. Knepley                                            0.0,  0.0,  -0.25, 0.0,  0.0, 0.5,   0.0,  0.0,  -0.25};
1836b9bf55e5SMatthew G. Knepley         PetscReal hexBackWeights[27]   = { 0.0,  0.0,   0.0,  0.0,  0.0, 0.0,  -0.25, 0.5,  -0.25,
1837b9bf55e5SMatthew G. Knepley                                            0.0,  0.0,   0.0,  0.0,  0.0, 0.0,   0.5,  0.0,   0.5,
1838b9bf55e5SMatthew G. Knepley                                            0.0,  0.0,   0.0,  0.0,  0.0, 0.0,  -0.25, 0.5,  -0.25};
1839b9bf55e5SMatthew G. Knepley         PetscReal hexTopWeights[27]    = { 0.0,  0.0,   0.0,  0.0,  0.0, 0.0,   0.0,  0.0,   0.0,
1840b9bf55e5SMatthew G. Knepley                                            0.0,  0.0,   0.0,  0.0,  0.0, 0.0,   0.0,  0.0,   0.0,
1841b9bf55e5SMatthew G. Knepley                                           -0.25, 0.5,  -0.25, 0.5,  0.0, 0.5,  -0.25, 0.5,  -0.25};
1842b9bf55e5SMatthew G. Knepley         PetscReal hexCenterWeights[27] = {-0.25, 0.25, -0.25, 0.25, 0.0, 0.25, -0.25, 0.25, -0.25,
1843b9bf55e5SMatthew G. Knepley                                            0.25, 0.0,   0.25, 0.0,  0.0, 0.0,   0.25, 0.0,   0.25,
1844b9bf55e5SMatthew G. Knepley                                           -0.25, 0.25, -0.25, 0.25, 0.0, 0.25, -0.25, 0.25, -0.25};
1845b9bf55e5SMatthew G. Knepley         PetscReal  *sdWeights2[9]      = {NULL, NULL, NULL, NULL, quaCenterWeights, NULL, NULL, NULL, NULL};
1846b9bf55e5SMatthew G. Knepley         PetscReal  *sdWeights3[27]     = {NULL, NULL, NULL, NULL, hexBottomWeights, NULL, NULL, NULL, NULL,
1847b9bf55e5SMatthew G. Knepley                                           NULL, hexFrontWeights, NULL, hexLeftWeights, hexCenterWeights, hexRightWeights, NULL, hexBackWeights, NULL,
1848b9bf55e5SMatthew G. Knepley                                           NULL, NULL, NULL, NULL, hexTopWeights,    NULL, NULL, NULL, NULL};
1849b9bf55e5SMatthew G. Knepley         PetscReal **sdWeights[4]       = {NULL, NULL, sdWeights2, sdWeights3};
1850b9bf55e5SMatthew G. Knepley 
1851b9bf55e5SMatthew G. Knepley         /* Missing entries in serendipity cell, only works for 8-node quad and 20-node hex */
1852b9bf55e5SMatthew G. Knepley         for (n = 0; n < elem->numNodes+s; ++n) {
1853b9bf55e5SMatthew G. Knepley           if (lexorder[n] >= 0) continue;
1854b9bf55e5SMatthew G. Knepley           for (d = 0; d < coordDim; ++d) cellCoords[n*coordDim+d] = 0.0;
1855b9bf55e5SMatthew G. Knepley           for (int bn = 0; bn < elem->numNodes+s; ++bn) {
1856b9bf55e5SMatthew G. Knepley             if (lexorder[bn] < 0) continue;
1857b9bf55e5SMatthew G. Knepley             const PetscReal *weights = sdWeights[coordDim][n];
1858b9bf55e5SMatthew G. Knepley             const PetscInt   bnode   = elem->nodes[lexorder[bn]];
1859b9bf55e5SMatthew G. Knepley             for (d = 0; d < coordDim; ++d) cellCoords[n*coordDim+d] += weights[bn] * (PetscReal) coords[bnode*3+d];
1860b9bf55e5SMatthew G. Knepley           }
1861b9bf55e5SMatthew G. Knepley         }
1862066ea43fSLisandro Dalcin       }
18635f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexVecSetClosure(cdm, section, coordinates, cell, cellCoords, INSERT_VALUES));
1864066ea43fSLisandro Dalcin     }
18655f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionDestroy(&section));
18665f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(cellCoords));
1867066ea43fSLisandro Dalcin 
1868066ea43fSLisandro Dalcin   } else {
1869066ea43fSLisandro Dalcin 
1870066ea43fSLisandro Dalcin     PetscInt    *nodeMap;
1871066ea43fSLisandro Dalcin     double      *coords = mesh ? mesh->nodelist->xyz : NULL;
1872066ea43fSLisandro Dalcin     PetscScalar *pointCoords;
1873066ea43fSLisandro Dalcin 
18745f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetLocalSection(cdm, &coordSection));
18755f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetNumFields(coordSection, 1));
18765f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, coordDim));
18770598e1a2SLisandro Dalcin     if (periodic) { /* we need to localize coordinates on cells */
18785f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionSetChart(coordSection, 0, numCells+numVerts));
1879f45c9589SStefano Zampini     } else {
18805f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionSetChart(coordSection, numCells, numCells+numVerts));
1881f45c9589SStefano Zampini     }
18820598e1a2SLisandro Dalcin     if (periodic) {
18830598e1a2SLisandro Dalcin       for (cell = 0; cell < numCells; ++cell) {
18840598e1a2SLisandro Dalcin         if (PetscUnlikely(PetscBTLookup(periodicCells, cell))) {
18850598e1a2SLisandro Dalcin           GmshElement *elem = mesh->elements + cell;
18860598e1a2SLisandro Dalcin           PetscInt dof = elem->numVerts * coordDim;
18875f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSectionSetDof(coordSection, cell, dof));
18885f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSectionSetFieldDof(coordSection, cell, 0, dof));
1889f45c9589SStefano Zampini         }
1890f45c9589SStefano Zampini       }
1891f45c9589SStefano Zampini     }
18920598e1a2SLisandro Dalcin     for (v = numCells; v < numCells+numVerts; ++v) {
18935f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionSetDof(coordSection, v, coordDim));
18945f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, coordDim));
18950598e1a2SLisandro Dalcin     }
18965f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetUp(coordSection));
1897066ea43fSLisandro Dalcin 
18985f80ce2aSJacob Faibussowitsch     CHKERRQ(DMCreateLocalVector(cdm, &coordinates));
18995f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArray(coordinates, &pointCoords));
19000598e1a2SLisandro Dalcin     if (periodic) {
19010598e1a2SLisandro Dalcin       for (cell = 0; cell < numCells; ++cell) {
19020598e1a2SLisandro Dalcin         if (PetscUnlikely(PetscBTLookup(periodicCells, cell))) {
19030598e1a2SLisandro Dalcin           GmshElement *elem = mesh->elements + cell;
19040598e1a2SLisandro Dalcin           PetscInt off, node;
19050598e1a2SLisandro Dalcin           for (v = 0; v < elem->numVerts; ++v)
19060598e1a2SLisandro Dalcin             cone[v] = elem->nodes[v];
19075f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexReorderCell(cdm, cell, cone));
19085f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSectionGetOffset(coordSection, cell, &off));
19090598e1a2SLisandro Dalcin           for (v = 0; v < elem->numVerts; ++v)
19100598e1a2SLisandro Dalcin             for (node = cone[v], d = 0; d < coordDim; ++d)
1911066ea43fSLisandro Dalcin               pointCoords[off++] = (PetscReal) coords[node*3+d];
1912331830f3SMatthew G. Knepley         }
1913331830f3SMatthew G. Knepley       }
1914331830f3SMatthew G. Knepley     }
19155f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(numVerts, &nodeMap));
19160598e1a2SLisandro Dalcin     for (n = 0; n < numNodes; n++)
19170598e1a2SLisandro Dalcin       if (mesh->vertexMap[n] >= 0)
1918066ea43fSLisandro Dalcin         nodeMap[mesh->vertexMap[n]] = n;
19190598e1a2SLisandro Dalcin     for (v = 0; v < numVerts; ++v) {
1920066ea43fSLisandro Dalcin       PetscInt off, node = nodeMap[v];
19215f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetOffset(coordSection, numCells + v, &off));
19220598e1a2SLisandro Dalcin       for (d = 0; d < coordDim; ++d)
1923066ea43fSLisandro Dalcin         pointCoords[off+d] = (PetscReal) coords[node*3+d];
19240598e1a2SLisandro Dalcin     }
19255f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(nodeMap));
19265f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArray(coordinates, &pointCoords));
1927066ea43fSLisandro Dalcin 
1928066ea43fSLisandro Dalcin   }
1929066ea43fSLisandro Dalcin 
19305f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates"));
19315f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetBlockSize(coordinates, coordDim));
19325f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetCoordinatesLocal(*dm, coordinates));
19335f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&coordinates));
19345f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetPeriodicity(*dm, periodic, NULL, NULL, NULL));
193511c56cb0SLisandro Dalcin 
19365f80ce2aSJacob Faibussowitsch   CHKERRQ(GmshMeshDestroy(&mesh));
19375f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscBTDestroy(&periodicVerts));
19385f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscBTDestroy(&periodicCells));
193911c56cb0SLisandro Dalcin 
1940066ea43fSLisandro Dalcin   if (highOrder && project)  {
1941066ea43fSLisandro Dalcin     PetscFE         fe;
1942066ea43fSLisandro Dalcin     const char      prefix[]   = "dm_plex_gmsh_project_";
1943066ea43fSLisandro Dalcin     PetscBool       continuity = periodic ? PETSC_FALSE : PETSC_TRUE;
1944066ea43fSLisandro Dalcin     PetscDTNodeType nodeType   = PETSCDTNODES_GAUSSJACOBI;
1945066ea43fSLisandro Dalcin 
1946066ea43fSLisandro Dalcin     if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */
1947066ea43fSLisandro Dalcin 
19485f80ce2aSJacob Faibussowitsch     CHKERRQ(GmshCreateFE(comm, prefix, isSimplex, continuity, nodeType, dim, coordDim, order, &fe));
19495f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_project_fe_view"));
19505f80ce2aSJacob Faibussowitsch     CHKERRQ(DMProjectCoordinates(*dm, fe));
19515f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFEDestroy(&fe));
1952066ea43fSLisandro Dalcin   }
1953066ea43fSLisandro Dalcin 
19545f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMPLEX_CreateGmsh,*dm,NULL,NULL,NULL));
1955331830f3SMatthew G. Knepley   PetscFunctionReturn(0);
1956331830f3SMatthew G. Knepley }
1957