xref: /petsc/src/dm/impls/plex/plexgmsh.c (revision 7d5b924439e5060890b204ae0b57ebb93a1767eb)
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;
200dd39110bSPierre Jolivet   n = PETSC_STATIC_ARRAY_LENGTH(GmshCellMap);
2010598e1a2SLisandro Dalcin   for (i = 0; i < n; ++i) {
2020598e1a2SLisandro Dalcin     GmshCellMap[i].cellType = -1;
203066ea43fSLisandro Dalcin     GmshCellMap[i].polytope = -1;
2040598e1a2SLisandro Dalcin   }
205dd39110bSPierre Jolivet   n = PETSC_STATIC_ARRAY_LENGTH(GmshCellTable);
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;                                                                  \
215dd39110bSPierre Jolivet     PetscCheck(_ct_ >= 0 && _ct_ < (int)PETSC_STATIC_ARRAY_LENGTH(GmshCellMap), 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) {
2429566063dSJacob Faibussowitsch     PetscCall(PetscFree(gmsh->wbuf));
2439566063dSJacob Faibussowitsch     PetscCall(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) {
2579566063dSJacob Faibussowitsch     PetscCall(PetscFree(gmsh->sbuf));
2589566063dSJacob Faibussowitsch     PetscCall(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;
2689566063dSJacob Faibussowitsch   PetscCall(PetscViewerRead(gmsh->viewer, buf, count, NULL, dtype));
2699566063dSJacob Faibussowitsch   if (gmsh->byteSwap) PetscCall(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;
2769566063dSJacob Faibussowitsch   PetscCall(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;
2839566063dSJacob Faibussowitsch   PetscCall(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;
2929566063dSJacob Faibussowitsch   PetscCall(GmshMatch(gmsh, Section, line, &match));
29328b400f6SJacob 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) {
3039566063dSJacob Faibussowitsch     PetscCall(GmshReadString(gmsh, line, 1));
3049566063dSJacob Faibussowitsch     PetscCall(GmshMatch(gmsh, "$Comments", line, &match));
305d6689ca9SLisandro Dalcin     if (!match) break;
306d6689ca9SLisandro Dalcin     while (PETSC_TRUE) {
3079566063dSJacob Faibussowitsch       PetscCall(GmshReadString(gmsh, line, 1));
3089566063dSJacob Faibussowitsch       PetscCall(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;
3189566063dSJacob Faibussowitsch   PetscCall(GmshReadString(gmsh, line, 1));
3199566063dSJacob Faibussowitsch   PetscCall(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)) {
3309566063dSJacob Faibussowitsch     PetscCall(GmshRead(gmsh, buf, count, PETSC_INT));
331698a79b9SLisandro Dalcin   } else  if (dataSize == sizeof(int)) {
332698a79b9SLisandro Dalcin     int *ibuf = NULL;
3339566063dSJacob Faibussowitsch     PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf));
3349566063dSJacob Faibussowitsch     PetscCall(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;
3389566063dSJacob Faibussowitsch     PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf));
3399566063dSJacob Faibussowitsch     PetscCall(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;
3439566063dSJacob Faibussowitsch     PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf));
3449566063dSJacob Faibussowitsch     PetscCall(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;
3539566063dSJacob Faibussowitsch   PetscCall(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;
3609566063dSJacob Faibussowitsch   PetscCall(GmshRead(gmsh, buf, count, PETSC_DOUBLE));
361de78e4feSLisandro Dalcin   PetscFunctionReturn(0);
362de78e4feSLisandro Dalcin }
363de78e4feSLisandro Dalcin 
364*7d5b9244SMatthew G. Knepley #define GMSH_MAX_TAGS 4
365*7d5b9244SMatthew G. Knepley 
366de78e4feSLisandro Dalcin typedef struct {
3670598e1a2SLisandro Dalcin   PetscInt id;      /* Entity ID */
3680598e1a2SLisandro Dalcin   PetscInt dim;     /* Dimension */
369de78e4feSLisandro Dalcin   double   bbox[6]; /* Bounding box */
370de78e4feSLisandro Dalcin   PetscInt numTags;             /* Size of tag array */
371*7d5b9244SMatthew G. Knepley   int      tags[GMSH_MAX_TAGS]; /* Tag array */
372de78e4feSLisandro Dalcin } GmshEntity;
373de78e4feSLisandro Dalcin 
374de78e4feSLisandro Dalcin typedef struct {
375730356f6SLisandro Dalcin   GmshEntity *entity[4];
376730356f6SLisandro Dalcin   PetscHMapI  entityMap[4];
377730356f6SLisandro Dalcin } GmshEntities;
378730356f6SLisandro Dalcin 
379698a79b9SLisandro Dalcin static PetscErrorCode GmshEntitiesCreate(PetscInt count[4], GmshEntities **entities)
380730356f6SLisandro Dalcin {
381730356f6SLisandro Dalcin   PetscInt       dim;
382730356f6SLisandro Dalcin 
383730356f6SLisandro Dalcin   PetscFunctionBegin;
3849566063dSJacob Faibussowitsch   PetscCall(PetscNew(entities));
385730356f6SLisandro Dalcin   for (dim = 0; dim < 4; ++dim) {
3869566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(count[dim], &(*entities)->entity[dim]));
3879566063dSJacob Faibussowitsch     PetscCall(PetscHMapICreate(&(*entities)->entityMap[dim]));
388730356f6SLisandro Dalcin   }
389730356f6SLisandro Dalcin   PetscFunctionReturn(0);
390730356f6SLisandro Dalcin }
391730356f6SLisandro Dalcin 
3920598e1a2SLisandro Dalcin static PetscErrorCode GmshEntitiesDestroy(GmshEntities **entities)
3930598e1a2SLisandro Dalcin {
3940598e1a2SLisandro Dalcin   PetscInt       dim;
3950598e1a2SLisandro Dalcin 
3960598e1a2SLisandro Dalcin   PetscFunctionBegin;
3970598e1a2SLisandro Dalcin   if (!*entities) PetscFunctionReturn(0);
3980598e1a2SLisandro Dalcin   for (dim = 0; dim < 4; ++dim) {
3999566063dSJacob Faibussowitsch     PetscCall(PetscFree((*entities)->entity[dim]));
4009566063dSJacob Faibussowitsch     PetscCall(PetscHMapIDestroy(&(*entities)->entityMap[dim]));
4010598e1a2SLisandro Dalcin   }
4029566063dSJacob Faibussowitsch   PetscCall(PetscFree((*entities)));
4030598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
4040598e1a2SLisandro Dalcin }
4050598e1a2SLisandro Dalcin 
406730356f6SLisandro Dalcin static PetscErrorCode GmshEntitiesAdd(GmshEntities *entities, PetscInt index, PetscInt dim, PetscInt eid, GmshEntity** entity)
407730356f6SLisandro Dalcin {
408730356f6SLisandro Dalcin   PetscFunctionBegin;
4099566063dSJacob Faibussowitsch   PetscCall(PetscHMapISet(entities->entityMap[dim], eid, index));
410730356f6SLisandro Dalcin   entities->entity[dim][index].dim = dim;
411730356f6SLisandro Dalcin   entities->entity[dim][index].id  = eid;
412730356f6SLisandro Dalcin   if (entity) *entity = &entities->entity[dim][index];
413730356f6SLisandro Dalcin   PetscFunctionReturn(0);
414730356f6SLisandro Dalcin }
415730356f6SLisandro Dalcin 
416730356f6SLisandro Dalcin static PetscErrorCode GmshEntitiesGet(GmshEntities *entities, PetscInt dim, PetscInt eid, GmshEntity** entity)
417730356f6SLisandro Dalcin {
418730356f6SLisandro Dalcin   PetscInt       index;
419730356f6SLisandro Dalcin 
420730356f6SLisandro Dalcin   PetscFunctionBegin;
4219566063dSJacob Faibussowitsch   PetscCall(PetscHMapIGet(entities->entityMap[dim], eid, &index));
422730356f6SLisandro Dalcin   *entity = &entities->entity[dim][index];
423730356f6SLisandro Dalcin   PetscFunctionReturn(0);
424730356f6SLisandro Dalcin }
425730356f6SLisandro Dalcin 
4260598e1a2SLisandro Dalcin typedef struct {
4270598e1a2SLisandro Dalcin   PetscInt *id;  /* Node IDs */
4280598e1a2SLisandro Dalcin   double   *xyz; /* Coordinates */
42981a1af93SMatthew G. Knepley   PetscInt *tag; /* Physical tag */
4300598e1a2SLisandro Dalcin } GmshNodes;
4310598e1a2SLisandro Dalcin 
4320598e1a2SLisandro Dalcin static PetscErrorCode GmshNodesCreate(PetscInt count, GmshNodes **nodes)
433730356f6SLisandro Dalcin {
434730356f6SLisandro Dalcin   PetscFunctionBegin;
4359566063dSJacob Faibussowitsch   PetscCall(PetscNew(nodes));
4369566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(count*1, &(*nodes)->id));
4379566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(count*3, &(*nodes)->xyz));
438*7d5b9244SMatthew G. Knepley   PetscCall(PetscMalloc1(count*GMSH_MAX_TAGS, &(*nodes)->tag));
4390598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
440730356f6SLisandro Dalcin }
4410598e1a2SLisandro Dalcin 
4420598e1a2SLisandro Dalcin static PetscErrorCode GmshNodesDestroy(GmshNodes **nodes)
4430598e1a2SLisandro Dalcin {
4440598e1a2SLisandro Dalcin   PetscFunctionBegin;
4450598e1a2SLisandro Dalcin   if (!*nodes) PetscFunctionReturn(0);
4469566063dSJacob Faibussowitsch   PetscCall(PetscFree((*nodes)->id));
4479566063dSJacob Faibussowitsch   PetscCall(PetscFree((*nodes)->xyz));
4489566063dSJacob Faibussowitsch   PetscCall(PetscFree((*nodes)->tag));
4499566063dSJacob Faibussowitsch   PetscCall(PetscFree((*nodes)));
450730356f6SLisandro Dalcin   PetscFunctionReturn(0);
451730356f6SLisandro Dalcin }
452730356f6SLisandro Dalcin 
453730356f6SLisandro Dalcin typedef struct {
4540598e1a2SLisandro Dalcin   PetscInt id;       /* Element ID */
4550598e1a2SLisandro Dalcin   PetscInt dim;      /* Dimension */
456de78e4feSLisandro Dalcin   PetscInt cellType; /* Cell type */
4570598e1a2SLisandro Dalcin   PetscInt numVerts; /* Size of vertex array */
458de78e4feSLisandro Dalcin   PetscInt numNodes; /* Size of node array */
4590598e1a2SLisandro Dalcin   PetscInt *nodes;   /* Vertex/Node array */
46081a1af93SMatthew G. Knepley   PetscInt numTags;             /* Size of physical tag array */
461*7d5b9244SMatthew G. Knepley   int      tags[GMSH_MAX_TAGS]; /* Physical tag array */
462de78e4feSLisandro Dalcin } GmshElement;
463de78e4feSLisandro Dalcin 
4640598e1a2SLisandro Dalcin static PetscErrorCode GmshElementsCreate(PetscInt count, GmshElement **elements)
4650598e1a2SLisandro Dalcin {
4660598e1a2SLisandro Dalcin   PetscFunctionBegin;
4679566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(count, elements));
4680598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
4690598e1a2SLisandro Dalcin }
4700598e1a2SLisandro Dalcin 
4710598e1a2SLisandro Dalcin static PetscErrorCode GmshElementsDestroy(GmshElement **elements)
4720598e1a2SLisandro Dalcin {
4730598e1a2SLisandro Dalcin   PetscFunctionBegin;
4740598e1a2SLisandro Dalcin   if (!*elements) PetscFunctionReturn(0);
4759566063dSJacob Faibussowitsch   PetscCall(PetscFree(*elements));
4760598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
4770598e1a2SLisandro Dalcin }
4780598e1a2SLisandro Dalcin 
4790598e1a2SLisandro Dalcin typedef struct {
4800598e1a2SLisandro Dalcin   PetscInt       dim;
481066ea43fSLisandro Dalcin   PetscInt       order;
4820598e1a2SLisandro Dalcin   GmshEntities  *entities;
4830598e1a2SLisandro Dalcin   PetscInt       numNodes;
4840598e1a2SLisandro Dalcin   GmshNodes     *nodelist;
4850598e1a2SLisandro Dalcin   PetscInt       numElems;
4860598e1a2SLisandro Dalcin   GmshElement   *elements;
4870598e1a2SLisandro Dalcin   PetscInt       numVerts;
4880598e1a2SLisandro Dalcin   PetscInt       numCells;
4890598e1a2SLisandro Dalcin   PetscInt      *periodMap;
4900598e1a2SLisandro Dalcin   PetscInt      *vertexMap;
4910598e1a2SLisandro Dalcin   PetscSegBuffer segbuf;
492a45dabc8SMatthew G. Knepley   PetscInt       numRegions;
493a45dabc8SMatthew G. Knepley   PetscInt      *regionTags;
494a45dabc8SMatthew G. Knepley   char         **regionNames;
4950598e1a2SLisandro Dalcin } GmshMesh;
4960598e1a2SLisandro Dalcin 
4970598e1a2SLisandro Dalcin static PetscErrorCode GmshMeshCreate(GmshMesh **mesh)
4980598e1a2SLisandro Dalcin {
4990598e1a2SLisandro Dalcin   PetscFunctionBegin;
5009566063dSJacob Faibussowitsch   PetscCall(PetscNew(mesh));
5019566063dSJacob Faibussowitsch   PetscCall(PetscSegBufferCreate(sizeof(PetscInt), 0, &(*mesh)->segbuf));
5020598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
5030598e1a2SLisandro Dalcin }
5040598e1a2SLisandro Dalcin 
5050598e1a2SLisandro Dalcin static PetscErrorCode GmshMeshDestroy(GmshMesh **mesh)
5060598e1a2SLisandro Dalcin {
507a45dabc8SMatthew G. Knepley   PetscInt       r;
5080598e1a2SLisandro Dalcin 
5090598e1a2SLisandro Dalcin   PetscFunctionBegin;
5100598e1a2SLisandro Dalcin   if (!*mesh) PetscFunctionReturn(0);
5119566063dSJacob Faibussowitsch   PetscCall(GmshEntitiesDestroy(&(*mesh)->entities));
5129566063dSJacob Faibussowitsch   PetscCall(GmshNodesDestroy(&(*mesh)->nodelist));
5139566063dSJacob Faibussowitsch   PetscCall(GmshElementsDestroy(&(*mesh)->elements));
5149566063dSJacob Faibussowitsch   PetscCall(PetscFree((*mesh)->periodMap));
5159566063dSJacob Faibussowitsch   PetscCall(PetscFree((*mesh)->vertexMap));
5169566063dSJacob Faibussowitsch   PetscCall(PetscSegBufferDestroy(&(*mesh)->segbuf));
5179566063dSJacob Faibussowitsch   for (r = 0; r < (*mesh)->numRegions; ++r) PetscCall(PetscFree((*mesh)->regionNames[r]));
5189566063dSJacob Faibussowitsch   PetscCall(PetscFree2((*mesh)->regionTags, (*mesh)->regionNames));
5199566063dSJacob Faibussowitsch   PetscCall(PetscFree((*mesh)));
5200598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
5210598e1a2SLisandro Dalcin }
5220598e1a2SLisandro Dalcin 
5230598e1a2SLisandro Dalcin static PetscErrorCode GmshReadNodes_v22(GmshFile *gmsh, GmshMesh *mesh)
524de78e4feSLisandro Dalcin {
525698a79b9SLisandro Dalcin   PetscViewer    viewer = gmsh->viewer;
526698a79b9SLisandro Dalcin   PetscBool      byteSwap = gmsh->byteSwap;
527de78e4feSLisandro Dalcin   char           line[PETSC_MAX_PATH_LEN];
528*7d5b9244SMatthew G. Knepley   int            n, t, num, nid, snum;
5290598e1a2SLisandro Dalcin   GmshNodes      *nodes;
530de78e4feSLisandro Dalcin 
531de78e4feSLisandro Dalcin   PetscFunctionBegin;
5329566063dSJacob Faibussowitsch   PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING));
533698a79b9SLisandro Dalcin   snum = sscanf(line, "%d", &num);
53408401ef6SPierre Jolivet   PetscCheck(snum == 1,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
5359566063dSJacob Faibussowitsch   PetscCall(GmshNodesCreate(num, &nodes));
5360598e1a2SLisandro Dalcin   mesh->numNodes = num;
5370598e1a2SLisandro Dalcin   mesh->nodelist = nodes;
5380598e1a2SLisandro Dalcin   for (n = 0; n < num; ++n) {
5390598e1a2SLisandro Dalcin     double *xyz = nodes->xyz + n*3;
5409566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM));
5419566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE));
5429566063dSJacob Faibussowitsch     if (byteSwap) PetscCall(PetscByteSwap(&nid, PETSC_ENUM, 1));
5439566063dSJacob Faibussowitsch     if (byteSwap) PetscCall(PetscByteSwap(xyz, PETSC_DOUBLE, 3));
5440598e1a2SLisandro Dalcin     nodes->id[n] = nid;
545*7d5b9244SMatthew G. Knepley     for (t = 0; t < GMSH_MAX_TAGS; ++t) nodes->tag[n*GMSH_MAX_TAGS+t] = -1;
54611c56cb0SLisandro Dalcin   }
54711c56cb0SLisandro Dalcin   PetscFunctionReturn(0);
54811c56cb0SLisandro Dalcin }
54911c56cb0SLisandro Dalcin 
550de78e4feSLisandro Dalcin /* Gmsh elements can be of any dimension/co-dimension, so we need to traverse the
551de78e4feSLisandro Dalcin    file contents multiple times to figure out the true number of cells and facets
552de78e4feSLisandro Dalcin    in the given mesh. To make this more efficient we read the file contents only
553de78e4feSLisandro Dalcin    once and store them in memory, while determining the true number of cells. */
5540598e1a2SLisandro Dalcin static PetscErrorCode GmshReadElements_v22(GmshFile* gmsh, GmshMesh *mesh)
55511c56cb0SLisandro Dalcin {
556698a79b9SLisandro Dalcin   PetscViewer    viewer = gmsh->viewer;
557698a79b9SLisandro Dalcin   PetscBool      binary = gmsh->binary;
558698a79b9SLisandro Dalcin   PetscBool      byteSwap = gmsh->byteSwap;
559de78e4feSLisandro Dalcin   char           line[PETSC_MAX_PATH_LEN];
5600598e1a2SLisandro Dalcin   int            i, c, p, num, ibuf[1+4+1000], snum;
5610598e1a2SLisandro Dalcin   int            cellType, numElem, numVerts, numNodes, numTags;
562df032b82SMatthew G. Knepley   GmshElement   *elements;
5630598e1a2SLisandro Dalcin   PetscInt      *nodeMap = gmsh->nodeMap;
564df032b82SMatthew G. Knepley 
565df032b82SMatthew G. Knepley   PetscFunctionBegin;
5669566063dSJacob Faibussowitsch   PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING));
567698a79b9SLisandro Dalcin   snum = sscanf(line, "%d", &num);
56808401ef6SPierre Jolivet   PetscCheck(snum == 1,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
5699566063dSJacob Faibussowitsch   PetscCall(GmshElementsCreate(num, &elements));
5700598e1a2SLisandro Dalcin   mesh->numElems = num;
5710598e1a2SLisandro Dalcin   mesh->elements = elements;
572698a79b9SLisandro Dalcin   for (c = 0; c < num;) {
5739566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM));
5749566063dSJacob Faibussowitsch     if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, 3));
5750598e1a2SLisandro Dalcin 
5760598e1a2SLisandro Dalcin     cellType = binary ? ibuf[0] : ibuf[1];
5770598e1a2SLisandro Dalcin     numElem  = binary ? ibuf[1] : 1;
578df032b82SMatthew G. Knepley     numTags  = ibuf[2];
5790598e1a2SLisandro Dalcin 
5809566063dSJacob Faibussowitsch     PetscCall(GmshCellTypeCheck(cellType));
5810598e1a2SLisandro Dalcin     numVerts = GmshCellMap[cellType].numVerts;
5820598e1a2SLisandro Dalcin     numNodes = GmshCellMap[cellType].numNodes;
5830598e1a2SLisandro Dalcin 
584df032b82SMatthew G. Knepley     for (i = 0; i < numElem; ++i, ++c) {
5850598e1a2SLisandro Dalcin       GmshElement *element = elements + c;
5860598e1a2SLisandro Dalcin       const int off = binary ? 0 : 1, nint = 1 + numTags + numNodes - off;
5870598e1a2SLisandro Dalcin       const int *id = ibuf, *nodes = ibuf + 1 + numTags, *tags = ibuf + 1;
5889566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, ibuf+off, nint, NULL, PETSC_ENUM));
5899566063dSJacob Faibussowitsch       if (byteSwap) PetscCall(PetscByteSwap(ibuf+off, PETSC_ENUM, nint));
5900598e1a2SLisandro Dalcin       element->id  = id[0];
5910598e1a2SLisandro Dalcin       element->dim = GmshCellMap[cellType].dim;
5920598e1a2SLisandro Dalcin       element->cellType = cellType;
5930598e1a2SLisandro Dalcin       element->numVerts = numVerts;
5940598e1a2SLisandro Dalcin       element->numNodes = numNodes;
595*7d5b9244SMatthew G. Knepley       element->numTags  = PetscMin(numTags, GMSH_MAX_TAGS);
5969566063dSJacob Faibussowitsch       PetscCall(PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes));
5970598e1a2SLisandro Dalcin       for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]];
5980598e1a2SLisandro Dalcin       for (p = 0; p < element->numTags;  p++) element->tags[p]  = tags[p];
599df032b82SMatthew G. Knepley     }
600df032b82SMatthew G. Knepley   }
601df032b82SMatthew G. Knepley   PetscFunctionReturn(0);
602df032b82SMatthew G. Knepley }
6037d282ae0SMichael Lange 
604de78e4feSLisandro Dalcin /*
605de78e4feSLisandro Dalcin $Entities
606de78e4feSLisandro Dalcin   numPoints(unsigned long) numCurves(unsigned long)
607de78e4feSLisandro Dalcin     numSurfaces(unsigned long) numVolumes(unsigned long)
608de78e4feSLisandro Dalcin   // points
609de78e4feSLisandro Dalcin   tag(int) boxMinX(double) boxMinY(double) boxMinZ(double)
610de78e4feSLisandro Dalcin     boxMaxX(double) boxMaxY(double) boxMaxZ(double)
611de78e4feSLisandro Dalcin     numPhysicals(unsigned long) phyisicalTag[...](int)
612de78e4feSLisandro Dalcin   ...
613de78e4feSLisandro Dalcin   // curves
614de78e4feSLisandro Dalcin   tag(int) boxMinX(double) boxMinY(double) boxMinZ(double)
615de78e4feSLisandro Dalcin      boxMaxX(double) boxMaxY(double) boxMaxZ(double)
616de78e4feSLisandro Dalcin      numPhysicals(unsigned long) physicalTag[...](int)
617de78e4feSLisandro Dalcin      numBREPVert(unsigned long) tagBREPVert[...](int)
618de78e4feSLisandro Dalcin   ...
619de78e4feSLisandro Dalcin   // surfaces
620de78e4feSLisandro Dalcin   tag(int) boxMinX(double) boxMinY(double) boxMinZ(double)
621de78e4feSLisandro Dalcin     boxMaxX(double) boxMaxY(double) boxMaxZ(double)
622de78e4feSLisandro Dalcin     numPhysicals(unsigned long) physicalTag[...](int)
623de78e4feSLisandro Dalcin     numBREPCurve(unsigned long) tagBREPCurve[...](int)
624de78e4feSLisandro Dalcin   ...
625de78e4feSLisandro Dalcin   // volumes
626de78e4feSLisandro Dalcin   tag(int) boxMinX(double) boxMinY(double) boxMinZ(double)
627de78e4feSLisandro Dalcin     boxMaxX(double) boxMaxY(double) boxMaxZ(double)
628de78e4feSLisandro Dalcin     numPhysicals(unsigned long) physicalTag[...](int)
629de78e4feSLisandro Dalcin     numBREPSurfaces(unsigned long) tagBREPSurfaces[...](int)
630de78e4feSLisandro Dalcin   ...
631de78e4feSLisandro Dalcin $EndEntities
632de78e4feSLisandro Dalcin */
6330598e1a2SLisandro Dalcin static PetscErrorCode GmshReadEntities_v40(GmshFile *gmsh, GmshMesh *mesh)
634de78e4feSLisandro Dalcin {
635698a79b9SLisandro Dalcin   PetscViewer    viewer = gmsh->viewer;
636698a79b9SLisandro Dalcin   PetscBool      byteSwap = gmsh->byteSwap;
637698a79b9SLisandro Dalcin   long           index, num, lbuf[4];
638730356f6SLisandro Dalcin   int            dim, eid, numTags, *ibuf, t;
639698a79b9SLisandro Dalcin   PetscInt       count[4], i;
640a5ba3d71SLisandro Dalcin   GmshEntity     *entity = NULL;
641de78e4feSLisandro Dalcin 
642de78e4feSLisandro Dalcin   PetscFunctionBegin;
6439566063dSJacob Faibussowitsch   PetscCall(PetscViewerRead(viewer, lbuf, 4, NULL, PETSC_LONG));
6449566063dSJacob Faibussowitsch   if (byteSwap) PetscCall(PetscByteSwap(lbuf, PETSC_LONG, 4));
645698a79b9SLisandro Dalcin   for (i = 0; i < 4; ++i) count[i] = lbuf[i];
6469566063dSJacob Faibussowitsch   PetscCall(GmshEntitiesCreate(count, &mesh->entities));
647de78e4feSLisandro Dalcin   for (dim = 0; dim < 4; ++dim) {
648730356f6SLisandro Dalcin     for (index = 0; index < count[dim]; ++index) {
6499566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, &eid, 1, NULL, PETSC_ENUM));
6509566063dSJacob Faibussowitsch       if (byteSwap) PetscCall(PetscByteSwap(&eid, PETSC_ENUM, 1));
6519566063dSJacob Faibussowitsch       PetscCall(GmshEntitiesAdd(mesh->entities, (PetscInt)index, dim, eid, &entity));
6529566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, entity->bbox, 6, NULL, PETSC_DOUBLE));
6539566063dSJacob Faibussowitsch       if (byteSwap) PetscCall(PetscByteSwap(entity->bbox, PETSC_DOUBLE, 6));
6549566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, &num, 1, NULL, PETSC_LONG));
6559566063dSJacob Faibussowitsch       if (byteSwap) PetscCall(PetscByteSwap(&num, PETSC_LONG, 1));
6569566063dSJacob Faibussowitsch       PetscCall(GmshBufferGet(gmsh, num, sizeof(int), &ibuf));
6579566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, ibuf, num, NULL, PETSC_ENUM));
6589566063dSJacob Faibussowitsch       if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, num));
659*7d5b9244SMatthew G. Knepley       entity->numTags = numTags = (int) PetscMin(num, GMSH_MAX_TAGS);
660de78e4feSLisandro Dalcin       for (t = 0; t < numTags; ++t) entity->tags[t] = ibuf[t];
661de78e4feSLisandro Dalcin       if (dim == 0) continue;
6629566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, &num, 1, NULL, PETSC_LONG));
6639566063dSJacob Faibussowitsch       if (byteSwap) PetscCall(PetscByteSwap(&num, PETSC_LONG, 1));
6649566063dSJacob Faibussowitsch       PetscCall(GmshBufferGet(gmsh, num, sizeof(int), &ibuf));
6659566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, ibuf, num, NULL, PETSC_ENUM));
6669566063dSJacob Faibussowitsch       if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, num));
667de78e4feSLisandro Dalcin     }
668de78e4feSLisandro Dalcin   }
669de78e4feSLisandro Dalcin   PetscFunctionReturn(0);
670de78e4feSLisandro Dalcin }
671de78e4feSLisandro Dalcin 
672de78e4feSLisandro Dalcin /*
673de78e4feSLisandro Dalcin $Nodes
674de78e4feSLisandro Dalcin   numEntityBlocks(unsigned long) numNodes(unsigned long)
675de78e4feSLisandro Dalcin   tagEntity(int) dimEntity(int) typeNode(int) numNodes(unsigned long)
676de78e4feSLisandro Dalcin     tag(int) x(double) y(double) z(double)
677de78e4feSLisandro Dalcin     ...
678de78e4feSLisandro Dalcin   ...
679de78e4feSLisandro Dalcin $EndNodes
680de78e4feSLisandro Dalcin */
6810598e1a2SLisandro Dalcin static PetscErrorCode GmshReadNodes_v40(GmshFile *gmsh, GmshMesh *mesh)
682de78e4feSLisandro Dalcin {
683698a79b9SLisandro Dalcin   PetscViewer    viewer = gmsh->viewer;
684698a79b9SLisandro Dalcin   PetscBool      byteSwap = gmsh->byteSwap;
685*7d5b9244SMatthew G. Knepley   long           block, node, n, t, numEntityBlocks, numTotalNodes, numNodes;
686de78e4feSLisandro Dalcin   int            info[3], nid;
6870598e1a2SLisandro Dalcin   GmshNodes      *nodes;
688de78e4feSLisandro Dalcin 
689de78e4feSLisandro Dalcin   PetscFunctionBegin;
6909566063dSJacob Faibussowitsch   PetscCall(PetscViewerRead(viewer, &numEntityBlocks, 1, NULL, PETSC_LONG));
6919566063dSJacob Faibussowitsch   if (byteSwap) PetscCall(PetscByteSwap(&numEntityBlocks, PETSC_LONG, 1));
6929566063dSJacob Faibussowitsch   PetscCall(PetscViewerRead(viewer, &numTotalNodes, 1, NULL, PETSC_LONG));
6939566063dSJacob Faibussowitsch   if (byteSwap) PetscCall(PetscByteSwap(&numTotalNodes, PETSC_LONG, 1));
6949566063dSJacob Faibussowitsch   PetscCall(GmshNodesCreate(numTotalNodes, &nodes));
6950598e1a2SLisandro Dalcin   mesh->numNodes = numTotalNodes;
6960598e1a2SLisandro Dalcin   mesh->nodelist = nodes;
6970598e1a2SLisandro Dalcin   for (n = 0, block = 0; block < numEntityBlocks; ++block) {
6989566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, info, 3, NULL, PETSC_ENUM));
6999566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, &numNodes, 1, NULL, PETSC_LONG));
7009566063dSJacob Faibussowitsch     if (byteSwap) PetscCall(PetscByteSwap(&numNodes, PETSC_LONG, 1));
701698a79b9SLisandro Dalcin     if (gmsh->binary) {
702277f51e8SBarry Smith       size_t nbytes = sizeof(int) + 3*sizeof(double);
703277f51e8SBarry Smith       char   *cbuf = NULL; /* dummy value to prevent warning from compiler about possible unitilized value */
7049566063dSJacob Faibussowitsch       PetscCall(GmshBufferGet(gmsh, numNodes, nbytes, &cbuf));
7059566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, cbuf, numNodes*nbytes, NULL, PETSC_CHAR));
7060598e1a2SLisandro Dalcin       for (node = 0; node < numNodes; ++node, ++n) {
707de78e4feSLisandro Dalcin         char   *cnid = cbuf + node*nbytes, *cxyz = cnid + sizeof(int);
7080598e1a2SLisandro Dalcin         double *xyz = nodes->xyz + n*3;
7099566063dSJacob Faibussowitsch         if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(cnid, PETSC_ENUM, 1));
7109566063dSJacob Faibussowitsch         if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(cxyz, PETSC_DOUBLE, 3));
7119566063dSJacob Faibussowitsch         PetscCall(PetscMemcpy(&nid, cnid, sizeof(int)));
7129566063dSJacob Faibussowitsch         PetscCall(PetscMemcpy(xyz, cxyz, 3*sizeof(double)));
7139566063dSJacob Faibussowitsch         if (byteSwap) PetscCall(PetscByteSwap(&nid, PETSC_ENUM, 1));
7149566063dSJacob Faibussowitsch         if (byteSwap) PetscCall(PetscByteSwap(xyz, PETSC_DOUBLE, 3));
7150598e1a2SLisandro Dalcin         nodes->id[n] = nid;
716*7d5b9244SMatthew G. Knepley         for (t = 0; t < GMSH_MAX_TAGS; ++t) nodes->tag[n*GMSH_MAX_TAGS+t] = -1;
717de78e4feSLisandro Dalcin       }
718de78e4feSLisandro Dalcin     } else {
7190598e1a2SLisandro Dalcin       for (node = 0; node < numNodes; ++node, ++n) {
7200598e1a2SLisandro Dalcin         double *xyz = nodes->xyz + n*3;
7219566063dSJacob Faibussowitsch         PetscCall(PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM));
7229566063dSJacob Faibussowitsch         PetscCall(PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE));
7239566063dSJacob Faibussowitsch         if (byteSwap) PetscCall(PetscByteSwap(&nid, PETSC_ENUM, 1));
7249566063dSJacob Faibussowitsch         if (byteSwap) PetscCall(PetscByteSwap(xyz, PETSC_DOUBLE, 3));
7250598e1a2SLisandro Dalcin         nodes->id[n] = nid;
726*7d5b9244SMatthew G. Knepley         for (t = 0; t < GMSH_MAX_TAGS; ++t) nodes->tag[n*GMSH_MAX_TAGS+t] = -1;
727de78e4feSLisandro Dalcin       }
728de78e4feSLisandro Dalcin     }
729de78e4feSLisandro Dalcin   }
730de78e4feSLisandro Dalcin   PetscFunctionReturn(0);
731de78e4feSLisandro Dalcin }
732de78e4feSLisandro Dalcin 
733de78e4feSLisandro Dalcin /*
734de78e4feSLisandro Dalcin $Elements
735de78e4feSLisandro Dalcin   numEntityBlocks(unsigned long) numElements(unsigned long)
736de78e4feSLisandro Dalcin   tagEntity(int) dimEntity(int) typeEle(int) numElements(unsigned long)
737de78e4feSLisandro Dalcin     tag(int) numVert[...](int)
738de78e4feSLisandro Dalcin     ...
739de78e4feSLisandro Dalcin   ...
740de78e4feSLisandro Dalcin $EndElements
741de78e4feSLisandro Dalcin */
7420598e1a2SLisandro Dalcin static PetscErrorCode GmshReadElements_v40(GmshFile *gmsh, GmshMesh *mesh)
743de78e4feSLisandro Dalcin {
744698a79b9SLisandro Dalcin   PetscViewer    viewer = gmsh->viewer;
745698a79b9SLisandro Dalcin   PetscBool      byteSwap = gmsh->byteSwap;
746de78e4feSLisandro Dalcin   long           c, block, numEntityBlocks, numTotalElements, elem, numElements;
747de78e4feSLisandro Dalcin   int            p, info[3], *ibuf = NULL;
7480598e1a2SLisandro Dalcin   int            eid, dim, cellType, numVerts, numNodes, numTags;
749a5ba3d71SLisandro Dalcin   GmshEntity     *entity = NULL;
750de78e4feSLisandro Dalcin   GmshElement    *elements;
7510598e1a2SLisandro Dalcin   PetscInt       *nodeMap = gmsh->nodeMap;
752de78e4feSLisandro Dalcin 
753de78e4feSLisandro Dalcin   PetscFunctionBegin;
7549566063dSJacob Faibussowitsch   PetscCall(PetscViewerRead(viewer, &numEntityBlocks, 1, NULL, PETSC_LONG));
7559566063dSJacob Faibussowitsch   if (byteSwap) PetscCall(PetscByteSwap(&numEntityBlocks, PETSC_LONG, 1));
7569566063dSJacob Faibussowitsch   PetscCall(PetscViewerRead(viewer, &numTotalElements, 1, NULL, PETSC_LONG));
7579566063dSJacob Faibussowitsch   if (byteSwap) PetscCall(PetscByteSwap(&numTotalElements, PETSC_LONG, 1));
7589566063dSJacob Faibussowitsch   PetscCall(GmshElementsCreate(numTotalElements, &elements));
7590598e1a2SLisandro Dalcin   mesh->numElems = numTotalElements;
7600598e1a2SLisandro Dalcin   mesh->elements = elements;
761de78e4feSLisandro Dalcin   for (c = 0, block = 0; block < numEntityBlocks; ++block) {
7629566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, info, 3, NULL, PETSC_ENUM));
7639566063dSJacob Faibussowitsch     if (byteSwap) PetscCall(PetscByteSwap(info, PETSC_ENUM, 3));
764de78e4feSLisandro Dalcin     eid = info[0]; dim = info[1]; cellType = info[2];
7659566063dSJacob Faibussowitsch     PetscCall(GmshEntitiesGet(mesh->entities, dim, eid, &entity));
7669566063dSJacob Faibussowitsch     PetscCall(GmshCellTypeCheck(cellType));
7670598e1a2SLisandro Dalcin     numVerts = GmshCellMap[cellType].numVerts;
7680598e1a2SLisandro Dalcin     numNodes = GmshCellMap[cellType].numNodes;
769730356f6SLisandro Dalcin     numTags  = entity->numTags;
7709566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, &numElements, 1, NULL, PETSC_LONG));
7719566063dSJacob Faibussowitsch     if (byteSwap) PetscCall(PetscByteSwap(&numElements, PETSC_LONG, 1));
7729566063dSJacob Faibussowitsch     PetscCall(GmshBufferGet(gmsh, (1+numNodes)*numElements, sizeof(int), &ibuf));
7739566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, ibuf, (1+numNodes)*numElements, NULL, PETSC_ENUM));
7749566063dSJacob Faibussowitsch     if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, (1+numNodes)*numElements));
775de78e4feSLisandro Dalcin     for (elem = 0; elem < numElements; ++elem, ++c) {
776de78e4feSLisandro Dalcin       GmshElement *element = elements + c;
7770598e1a2SLisandro Dalcin       const int *id = ibuf + elem*(1+numNodes), *nodes = id + 1;
7780598e1a2SLisandro Dalcin       element->id  = id[0];
779de78e4feSLisandro Dalcin       element->dim = dim;
780de78e4feSLisandro Dalcin       element->cellType = cellType;
7810598e1a2SLisandro Dalcin       element->numVerts = numVerts;
782de78e4feSLisandro Dalcin       element->numNodes = numNodes;
783de78e4feSLisandro Dalcin       element->numTags  = numTags;
7849566063dSJacob Faibussowitsch       PetscCall(PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes));
7850598e1a2SLisandro Dalcin       for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]];
7860598e1a2SLisandro Dalcin       for (p = 0; p < element->numTags;  p++) element->tags[p]  = entity->tags[p];
787de78e4feSLisandro Dalcin     }
788de78e4feSLisandro Dalcin   }
789698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
790698a79b9SLisandro Dalcin }
791698a79b9SLisandro Dalcin 
7920598e1a2SLisandro Dalcin static PetscErrorCode GmshReadPeriodic_v40(GmshFile *gmsh, PetscInt periodicMap[])
793698a79b9SLisandro Dalcin {
794698a79b9SLisandro Dalcin   PetscViewer    viewer = gmsh->viewer;
795698a79b9SLisandro Dalcin   int            fileFormat = gmsh->fileFormat;
796698a79b9SLisandro Dalcin   PetscBool      binary = gmsh->binary;
797698a79b9SLisandro Dalcin   PetscBool      byteSwap = gmsh->byteSwap;
798698a79b9SLisandro Dalcin   int            numPeriodic, snum, i;
799698a79b9SLisandro Dalcin   char           line[PETSC_MAX_PATH_LEN];
8000598e1a2SLisandro Dalcin   PetscInt       *nodeMap = gmsh->nodeMap;
801698a79b9SLisandro Dalcin 
802698a79b9SLisandro Dalcin   PetscFunctionBegin;
803698a79b9SLisandro Dalcin   if (fileFormat == 22 || !binary) {
8049566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING));
805698a79b9SLisandro Dalcin     snum = sscanf(line, "%d", &numPeriodic);
80608401ef6SPierre Jolivet     PetscCheck(snum == 1,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
807698a79b9SLisandro Dalcin   } else {
8089566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, &numPeriodic, 1, NULL, PETSC_ENUM));
8099566063dSJacob Faibussowitsch     if (byteSwap) PetscCall(PetscByteSwap(&numPeriodic, PETSC_ENUM, 1));
810698a79b9SLisandro Dalcin   }
811698a79b9SLisandro Dalcin   for (i = 0; i < numPeriodic; i++) {
8129dddd249SSatish Balay     int    ibuf[3], correspondingDim = -1, correspondingTag = -1, primaryTag = -1, correspondingNode, primaryNode;
813698a79b9SLisandro Dalcin     long   j, nNodes;
814698a79b9SLisandro Dalcin     double affine[16];
815698a79b9SLisandro Dalcin 
816698a79b9SLisandro Dalcin     if (fileFormat == 22 || !binary) {
8179566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, line, 3, NULL, PETSC_STRING));
8189dddd249SSatish Balay       snum = sscanf(line, "%d %d %d", &correspondingDim, &correspondingTag, &primaryTag);
81908401ef6SPierre Jolivet       PetscCheck(snum == 3,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
820698a79b9SLisandro Dalcin     } else {
8219566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM));
8229566063dSJacob Faibussowitsch       if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, 3));
8239dddd249SSatish Balay       correspondingDim = ibuf[0]; correspondingTag = ibuf[1]; primaryTag = ibuf[2];
824698a79b9SLisandro Dalcin     }
8259dddd249SSatish Balay     (void)correspondingDim; (void)correspondingTag; (void)primaryTag; /* unused */
826698a79b9SLisandro Dalcin 
827698a79b9SLisandro Dalcin     if (fileFormat == 22 || !binary) {
8289566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING));
829698a79b9SLisandro Dalcin       snum = sscanf(line, "%ld", &nNodes);
8304c500f23SPierre Jolivet       if (snum != 1) { /* discard transformation and try again */
8319566063dSJacob Faibussowitsch         PetscCall(PetscViewerRead(viewer, line, -PETSC_MAX_PATH_LEN, NULL, PETSC_STRING));
8329566063dSJacob Faibussowitsch         PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING));
833698a79b9SLisandro Dalcin         snum = sscanf(line, "%ld", &nNodes);
83408401ef6SPierre Jolivet         PetscCheck(snum == 1,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
835698a79b9SLisandro Dalcin       }
836698a79b9SLisandro Dalcin     } else {
8379566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, &nNodes, 1, NULL, PETSC_LONG));
8389566063dSJacob Faibussowitsch       if (byteSwap) PetscCall(PetscByteSwap(&nNodes, PETSC_LONG, 1));
8394c500f23SPierre Jolivet       if (nNodes == -1) { /* discard transformation and try again */
8409566063dSJacob Faibussowitsch         PetscCall(PetscViewerRead(viewer, affine, 16, NULL, PETSC_DOUBLE));
8419566063dSJacob Faibussowitsch         PetscCall(PetscViewerRead(viewer, &nNodes, 1, NULL, PETSC_LONG));
8429566063dSJacob Faibussowitsch         if (byteSwap) PetscCall(PetscByteSwap(&nNodes, PETSC_LONG, 1));
843698a79b9SLisandro Dalcin       }
844698a79b9SLisandro Dalcin     }
845698a79b9SLisandro Dalcin 
846698a79b9SLisandro Dalcin     for (j = 0; j < nNodes; j++) {
847698a79b9SLisandro Dalcin       if (fileFormat == 22 || !binary) {
8489566063dSJacob Faibussowitsch         PetscCall(PetscViewerRead(viewer, line, 2, NULL, PETSC_STRING));
8499dddd249SSatish Balay         snum = sscanf(line, "%d %d", &correspondingNode, &primaryNode);
85008401ef6SPierre Jolivet         PetscCheck(snum == 2,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
851698a79b9SLisandro Dalcin       } else {
8529566063dSJacob Faibussowitsch         PetscCall(PetscViewerRead(viewer, ibuf, 2, NULL, PETSC_ENUM));
8539566063dSJacob Faibussowitsch         if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, 2));
8549dddd249SSatish Balay         correspondingNode = ibuf[0]; primaryNode = ibuf[1];
855698a79b9SLisandro Dalcin       }
8569dddd249SSatish Balay       correspondingNode  = (int) nodeMap[correspondingNode];
8579dddd249SSatish Balay       primaryNode = (int) nodeMap[primaryNode];
8589dddd249SSatish Balay       periodicMap[correspondingNode] = primaryNode;
859698a79b9SLisandro Dalcin     }
860698a79b9SLisandro Dalcin   }
861698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
862698a79b9SLisandro Dalcin }
863698a79b9SLisandro Dalcin 
8640598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
865698a79b9SLisandro Dalcin $Entities
866698a79b9SLisandro Dalcin   numPoints(size_t) numCurves(size_t)
867698a79b9SLisandro Dalcin     numSurfaces(size_t) numVolumes(size_t)
868698a79b9SLisandro Dalcin   pointTag(int) X(double) Y(double) Z(double)
869698a79b9SLisandro Dalcin     numPhysicalTags(size_t) physicalTag(int) ...
870698a79b9SLisandro Dalcin   ...
871698a79b9SLisandro Dalcin   curveTag(int) minX(double) minY(double) minZ(double)
872698a79b9SLisandro Dalcin     maxX(double) maxY(double) maxZ(double)
873698a79b9SLisandro Dalcin     numPhysicalTags(size_t) physicalTag(int) ...
874698a79b9SLisandro Dalcin     numBoundingPoints(size_t) pointTag(int) ...
875698a79b9SLisandro Dalcin   ...
876698a79b9SLisandro Dalcin   surfaceTag(int) minX(double) minY(double) minZ(double)
877698a79b9SLisandro Dalcin     maxX(double) maxY(double) maxZ(double)
878698a79b9SLisandro Dalcin     numPhysicalTags(size_t) physicalTag(int) ...
879698a79b9SLisandro Dalcin     numBoundingCurves(size_t) curveTag(int) ...
880698a79b9SLisandro Dalcin   ...
881698a79b9SLisandro Dalcin   volumeTag(int) minX(double) minY(double) minZ(double)
882698a79b9SLisandro Dalcin     maxX(double) maxY(double) maxZ(double)
883698a79b9SLisandro Dalcin     numPhysicalTags(size_t) physicalTag(int) ...
884698a79b9SLisandro Dalcin     numBoundngSurfaces(size_t) surfaceTag(int) ...
885698a79b9SLisandro Dalcin   ...
886698a79b9SLisandro Dalcin $EndEntities
887698a79b9SLisandro Dalcin */
8880598e1a2SLisandro Dalcin static PetscErrorCode GmshReadEntities_v41(GmshFile *gmsh, GmshMesh *mesh)
889698a79b9SLisandro Dalcin {
890698a79b9SLisandro Dalcin   PetscInt       count[4], index, numTags, i;
891698a79b9SLisandro Dalcin   int            dim, eid, *tags = NULL;
892698a79b9SLisandro Dalcin   GmshEntity     *entity = NULL;
893698a79b9SLisandro Dalcin 
894698a79b9SLisandro Dalcin   PetscFunctionBegin;
8959566063dSJacob Faibussowitsch   PetscCall(GmshReadSize(gmsh, count, 4));
8969566063dSJacob Faibussowitsch   PetscCall(GmshEntitiesCreate(count, &mesh->entities));
897698a79b9SLisandro Dalcin   for (dim = 0; dim < 4; ++dim) {
898698a79b9SLisandro Dalcin     for (index = 0; index < count[dim]; ++index) {
8999566063dSJacob Faibussowitsch       PetscCall(GmshReadInt(gmsh, &eid, 1));
9009566063dSJacob Faibussowitsch       PetscCall(GmshEntitiesAdd(mesh->entities, (PetscInt)index, dim, eid, &entity));
9019566063dSJacob Faibussowitsch       PetscCall(GmshReadDouble(gmsh, entity->bbox, (dim == 0) ? 3 : 6));
9029566063dSJacob Faibussowitsch       PetscCall(GmshReadSize(gmsh, &numTags, 1));
9039566063dSJacob Faibussowitsch       PetscCall(GmshBufferGet(gmsh, numTags, sizeof(int), &tags));
9049566063dSJacob Faibussowitsch       PetscCall(GmshReadInt(gmsh, tags, numTags));
905*7d5b9244SMatthew G. Knepley       PetscCheck(numTags <= GMSH_MAX_TAGS, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PETSc currently supports up to 4 tags per entity, not %" PetscInt_FMT, numTags);
906*7d5b9244SMatthew G. Knepley       entity->numTags = numTags;
907698a79b9SLisandro Dalcin       for (i = 0; i < entity->numTags; ++i) entity->tags[i] = tags[i];
908698a79b9SLisandro Dalcin       if (dim == 0) continue;
9099566063dSJacob Faibussowitsch       PetscCall(GmshReadSize(gmsh, &numTags, 1));
9109566063dSJacob Faibussowitsch       PetscCall(GmshBufferGet(gmsh, numTags, sizeof(int), &tags));
9119566063dSJacob Faibussowitsch       PetscCall(GmshReadInt(gmsh, tags, numTags));
91281a1af93SMatthew G. Knepley       /* Currently, we do not save the ids for the bounding entities */
913698a79b9SLisandro Dalcin     }
914698a79b9SLisandro Dalcin   }
915698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
916698a79b9SLisandro Dalcin }
917698a79b9SLisandro Dalcin 
91833a088b6SMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
919698a79b9SLisandro Dalcin $Nodes
920698a79b9SLisandro Dalcin   numEntityBlocks(size_t) numNodes(size_t)
921698a79b9SLisandro Dalcin     minNodeTag(size_t) maxNodeTag(size_t)
922698a79b9SLisandro Dalcin   entityDim(int) entityTag(int) parametric(int; 0 or 1) numNodesBlock(size_t)
923698a79b9SLisandro Dalcin     nodeTag(size_t)
924698a79b9SLisandro Dalcin     ...
925698a79b9SLisandro Dalcin     x(double) y(double) z(double)
926698a79b9SLisandro Dalcin        < u(double; if parametric and entityDim = 1 or entityDim = 2) >
927698a79b9SLisandro Dalcin        < v(double; if parametric and entityDim = 2) >
928698a79b9SLisandro Dalcin     ...
929698a79b9SLisandro Dalcin   ...
930698a79b9SLisandro Dalcin $EndNodes
931698a79b9SLisandro Dalcin */
9320598e1a2SLisandro Dalcin static PetscErrorCode GmshReadNodes_v41(GmshFile *gmsh, GmshMesh *mesh)
933698a79b9SLisandro Dalcin {
93481a1af93SMatthew G. Knepley   int            info[3], dim, eid, parametric;
935*7d5b9244SMatthew G. Knepley   PetscInt       sizes[4], numEntityBlocks, numTags, t, numNodes, numNodesBlock = 0, block, node, n;
93681a1af93SMatthew G. Knepley   GmshEntity     *entity = NULL;
9370598e1a2SLisandro Dalcin   GmshNodes      *nodes;
938698a79b9SLisandro Dalcin 
939698a79b9SLisandro Dalcin   PetscFunctionBegin;
9409566063dSJacob Faibussowitsch   PetscCall(GmshReadSize(gmsh, sizes, 4));
9410598e1a2SLisandro Dalcin   numEntityBlocks = sizes[0]; numNodes = sizes[1];
9429566063dSJacob Faibussowitsch   PetscCall(GmshNodesCreate(numNodes, &nodes));
9430598e1a2SLisandro Dalcin   mesh->numNodes = numNodes;
9440598e1a2SLisandro Dalcin   mesh->nodelist = nodes;
945698a79b9SLisandro Dalcin   for (block = 0, node = 0; block < numEntityBlocks; ++block, node += numNodesBlock) {
9469566063dSJacob Faibussowitsch     PetscCall(GmshReadInt(gmsh, info, 3));
94781a1af93SMatthew G. Knepley     dim = info[0]; eid = info[1]; parametric = info[2];
9489566063dSJacob Faibussowitsch     PetscCall(GmshEntitiesGet(mesh->entities, dim, eid, &entity));
949*7d5b9244SMatthew G. Knepley     numTags = entity->numTags;
95081a1af93SMatthew G. Knepley     PetscCheck(!parametric, PETSC_COMM_SELF, PETSC_ERR_SUP, "Parametric coordinates not supported");
9519566063dSJacob Faibussowitsch     PetscCall(GmshReadSize(gmsh, &numNodesBlock, 1));
9529566063dSJacob Faibussowitsch     PetscCall(GmshReadSize(gmsh, nodes->id+node, numNodesBlock));
9539566063dSJacob Faibussowitsch     PetscCall(GmshReadDouble(gmsh, nodes->xyz+node*3, numNodesBlock*3));
954*7d5b9244SMatthew G. Knepley     for (n = 0; n < numNodesBlock; ++n) {
955*7d5b9244SMatthew G. Knepley       PetscInt *tags = &nodes->tag[node*GMSH_MAX_TAGS];
956*7d5b9244SMatthew G. Knepley 
957*7d5b9244SMatthew G. Knepley       for (t = 0; t < numTags; ++t) tags[n*GMSH_MAX_TAGS+t] = entity->tags[t];
958*7d5b9244SMatthew G. Knepley       for (t = numTags; t < GMSH_MAX_TAGS; ++t) tags[n*GMSH_MAX_TAGS+t] = -1;
959*7d5b9244SMatthew G. Knepley     }
960698a79b9SLisandro Dalcin   }
9610598e1a2SLisandro Dalcin   gmsh->nodeStart = sizes[2];
9620598e1a2SLisandro Dalcin   gmsh->nodeEnd   = sizes[3]+1;
963698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
964698a79b9SLisandro Dalcin }
965698a79b9SLisandro Dalcin 
96633a088b6SMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
967698a79b9SLisandro Dalcin $Elements
968698a79b9SLisandro Dalcin   numEntityBlocks(size_t) numElements(size_t)
969698a79b9SLisandro Dalcin     minElementTag(size_t) maxElementTag(size_t)
970698a79b9SLisandro Dalcin   entityDim(int) entityTag(int) elementType(int; see below) numElementsBlock(size_t)
971698a79b9SLisandro Dalcin     elementTag(size_t) nodeTag(size_t) ...
972698a79b9SLisandro Dalcin     ...
973698a79b9SLisandro Dalcin   ...
974698a79b9SLisandro Dalcin $EndElements
975698a79b9SLisandro Dalcin */
9760598e1a2SLisandro Dalcin static PetscErrorCode GmshReadElements_v41(GmshFile *gmsh, GmshMesh *mesh)
977698a79b9SLisandro Dalcin {
9780598e1a2SLisandro Dalcin   int            info[3], eid, dim, cellType;
9790598e1a2SLisandro Dalcin   PetscInt       sizes[4], *ibuf = NULL, numEntityBlocks, numElements, numBlockElements, numVerts, numNodes, numTags, block, elem, c, p;
980698a79b9SLisandro Dalcin   GmshEntity     *entity = NULL;
981698a79b9SLisandro Dalcin   GmshElement    *elements;
9820598e1a2SLisandro Dalcin   PetscInt       *nodeMap = gmsh->nodeMap;
983698a79b9SLisandro Dalcin 
984698a79b9SLisandro Dalcin   PetscFunctionBegin;
9859566063dSJacob Faibussowitsch   PetscCall(GmshReadSize(gmsh, sizes, 4));
986698a79b9SLisandro Dalcin   numEntityBlocks = sizes[0]; numElements = sizes[1];
9879566063dSJacob Faibussowitsch   PetscCall(GmshElementsCreate(numElements, &elements));
9880598e1a2SLisandro Dalcin   mesh->numElems = numElements;
9890598e1a2SLisandro Dalcin   mesh->elements = elements;
990698a79b9SLisandro Dalcin   for (c = 0, block = 0; block < numEntityBlocks; ++block) {
9919566063dSJacob Faibussowitsch     PetscCall(GmshReadInt(gmsh, info, 3));
992698a79b9SLisandro Dalcin     dim = info[0]; eid = info[1]; cellType = info[2];
9939566063dSJacob Faibussowitsch     PetscCall(GmshEntitiesGet(mesh->entities, dim, eid, &entity));
9949566063dSJacob Faibussowitsch     PetscCall(GmshCellTypeCheck(cellType));
9950598e1a2SLisandro Dalcin     numVerts = GmshCellMap[cellType].numVerts;
9960598e1a2SLisandro Dalcin     numNodes = GmshCellMap[cellType].numNodes;
997*7d5b9244SMatthew G. Knepley     numTags  = entity->numTags;
9989566063dSJacob Faibussowitsch     PetscCall(GmshReadSize(gmsh, &numBlockElements, 1));
9999566063dSJacob Faibussowitsch     PetscCall(GmshBufferGet(gmsh, (1+numNodes)*numBlockElements, sizeof(PetscInt), &ibuf));
10009566063dSJacob Faibussowitsch     PetscCall(GmshReadSize(gmsh, ibuf, (1+numNodes)*numBlockElements));
1001698a79b9SLisandro Dalcin     for (elem = 0; elem < numBlockElements; ++elem, ++c) {
1002698a79b9SLisandro Dalcin       GmshElement *element = elements + c;
10030598e1a2SLisandro Dalcin       const PetscInt *id = ibuf + elem*(1+numNodes), *nodes = id + 1;
1004698a79b9SLisandro Dalcin       element->id  = id[0];
1005698a79b9SLisandro Dalcin       element->dim = dim;
1006698a79b9SLisandro Dalcin       element->cellType = cellType;
10070598e1a2SLisandro Dalcin       element->numVerts = numVerts;
1008698a79b9SLisandro Dalcin       element->numNodes = numNodes;
1009698a79b9SLisandro Dalcin       element->numTags  = numTags;
10109566063dSJacob Faibussowitsch       PetscCall(PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes));
10110598e1a2SLisandro Dalcin       for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]];
10120598e1a2SLisandro Dalcin       for (p = 0; p < element->numTags;  p++) element->tags[p]  = entity->tags[p];
1013698a79b9SLisandro Dalcin     }
1014698a79b9SLisandro Dalcin   }
1015698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
1016698a79b9SLisandro Dalcin }
1017698a79b9SLisandro Dalcin 
10180598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
1019698a79b9SLisandro Dalcin $Periodic
1020698a79b9SLisandro Dalcin   numPeriodicLinks(size_t)
10219dddd249SSatish Balay   entityDim(int) entityTag(int) entityTagPrimary(int)
1022698a79b9SLisandro Dalcin   numAffine(size_t) value(double) ...
1023698a79b9SLisandro Dalcin   numCorrespondingNodes(size_t)
10249dddd249SSatish Balay     nodeTag(size_t) nodeTagPrimary(size_t)
1025698a79b9SLisandro Dalcin     ...
1026698a79b9SLisandro Dalcin   ...
1027698a79b9SLisandro Dalcin $EndPeriodic
1028698a79b9SLisandro Dalcin */
10290598e1a2SLisandro Dalcin static PetscErrorCode GmshReadPeriodic_v41(GmshFile *gmsh, PetscInt periodicMap[])
1030698a79b9SLisandro Dalcin {
1031698a79b9SLisandro Dalcin   int            info[3];
1032698a79b9SLisandro Dalcin   double         dbuf[16];
10330598e1a2SLisandro Dalcin   PetscInt       numPeriodicLinks, numAffine, numCorrespondingNodes, *nodeTags = NULL, link, node;
10340598e1a2SLisandro Dalcin   PetscInt       *nodeMap = gmsh->nodeMap;
1035698a79b9SLisandro Dalcin 
1036698a79b9SLisandro Dalcin   PetscFunctionBegin;
10379566063dSJacob Faibussowitsch   PetscCall(GmshReadSize(gmsh, &numPeriodicLinks, 1));
1038698a79b9SLisandro Dalcin   for (link = 0; link < numPeriodicLinks; ++link) {
10399566063dSJacob Faibussowitsch     PetscCall(GmshReadInt(gmsh, info, 3));
10409566063dSJacob Faibussowitsch     PetscCall(GmshReadSize(gmsh, &numAffine, 1));
10419566063dSJacob Faibussowitsch     PetscCall(GmshReadDouble(gmsh, dbuf, numAffine));
10429566063dSJacob Faibussowitsch     PetscCall(GmshReadSize(gmsh, &numCorrespondingNodes, 1));
10439566063dSJacob Faibussowitsch     PetscCall(GmshBufferGet(gmsh, numCorrespondingNodes, sizeof(PetscInt), &nodeTags));
10449566063dSJacob Faibussowitsch     PetscCall(GmshReadSize(gmsh, nodeTags, numCorrespondingNodes*2));
1045698a79b9SLisandro Dalcin     for (node = 0; node < numCorrespondingNodes; ++node) {
10469dddd249SSatish Balay       PetscInt correspondingNode = nodeMap[nodeTags[node*2+0]];
10479dddd249SSatish Balay       PetscInt primaryNode = nodeMap[nodeTags[node*2+1]];
10489dddd249SSatish Balay       periodicMap[correspondingNode] = primaryNode;
1049698a79b9SLisandro Dalcin     }
1050698a79b9SLisandro Dalcin   }
1051698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
1052698a79b9SLisandro Dalcin }
1053698a79b9SLisandro Dalcin 
10540598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
1055d6689ca9SLisandro Dalcin $MeshFormat // same as MSH version 2
1056d6689ca9SLisandro Dalcin   version(ASCII double; currently 4.1)
1057d6689ca9SLisandro Dalcin   file-type(ASCII int; 0 for ASCII mode, 1 for binary mode)
1058d6689ca9SLisandro Dalcin   data-size(ASCII int; sizeof(size_t))
1059d6689ca9SLisandro Dalcin   < int with value one; only in binary mode, to detect endianness >
1060d6689ca9SLisandro Dalcin $EndMeshFormat
1061d6689ca9SLisandro Dalcin */
10620598e1a2SLisandro Dalcin static PetscErrorCode GmshReadMeshFormat(GmshFile *gmsh)
1063698a79b9SLisandro Dalcin {
1064698a79b9SLisandro Dalcin   char           line[PETSC_MAX_PATH_LEN];
1065698a79b9SLisandro Dalcin   int            snum, fileType, fileFormat, dataSize, checkEndian;
1066698a79b9SLisandro Dalcin   float          version;
1067698a79b9SLisandro Dalcin 
1068698a79b9SLisandro Dalcin   PetscFunctionBegin;
10699566063dSJacob Faibussowitsch   PetscCall(GmshReadString(gmsh, line, 3));
1070698a79b9SLisandro Dalcin   snum = sscanf(line, "%f %d %d", &version, &fileType, &dataSize);
107108401ef6SPierre Jolivet   PetscCheck(snum == 3,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line);
107208401ef6SPierre Jolivet   PetscCheck(version >= 2.2,PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at least 2.2", (double)version);
10732c71b3e2SJacob Faibussowitsch   PetscCheckFalse((int)version == 3,PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f not supported", (double)version);
107408401ef6SPierre Jolivet   PetscCheck(version <= 4.1,PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at most 4.1", (double)version);
107508401ef6SPierre Jolivet   PetscCheck(!gmsh->binary || fileType,PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Viewer is binary but Gmsh file is ASCII");
107608401ef6SPierre Jolivet   PetscCheck(gmsh->binary || !fileType,PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Viewer is ASCII but Gmsh file is binary");
1077af7a0b9fSSatish Balay   fileFormat = (int)roundf(version*10);
10782c71b3e2SJacob 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);
10792c71b3e2SJacob 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);
1080698a79b9SLisandro Dalcin   gmsh->fileFormat = fileFormat;
1081698a79b9SLisandro Dalcin   gmsh->dataSize = dataSize;
1082698a79b9SLisandro Dalcin   gmsh->byteSwap = PETSC_FALSE;
1083698a79b9SLisandro Dalcin   if (gmsh->binary) {
10849566063dSJacob Faibussowitsch     PetscCall(GmshReadInt(gmsh, &checkEndian, 1));
1085698a79b9SLisandro Dalcin     if (checkEndian != 1) {
10869566063dSJacob Faibussowitsch       PetscCall(PetscByteSwap(&checkEndian, PETSC_ENUM, 1));
108708401ef6SPierre Jolivet       PetscCheck(checkEndian == 1,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to detect endianness in Gmsh file header: %s", line);
1088698a79b9SLisandro Dalcin       gmsh->byteSwap = PETSC_TRUE;
1089698a79b9SLisandro Dalcin     }
1090698a79b9SLisandro Dalcin   }
1091698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
1092698a79b9SLisandro Dalcin }
1093698a79b9SLisandro Dalcin 
10941f643af3SLisandro Dalcin /*
10951f643af3SLisandro Dalcin PhysicalNames
10961f643af3SLisandro Dalcin   numPhysicalNames(ASCII int)
10971f643af3SLisandro Dalcin   dimension(ASCII int) physicalTag(ASCII int) "name"(127 characters max)
10981f643af3SLisandro Dalcin   ...
10991f643af3SLisandro Dalcin $EndPhysicalNames
11001f643af3SLisandro Dalcin */
1101a45dabc8SMatthew G. Knepley static PetscErrorCode GmshReadPhysicalNames(GmshFile *gmsh, GmshMesh *mesh)
1102698a79b9SLisandro Dalcin {
11035f5cd6d5SMatthew G. Knepley   char           line[PETSC_MAX_PATH_LEN], name[128+2], *p, *q, *r;
1104a45dabc8SMatthew G. Knepley   int            snum, region, dim, tag;
1105698a79b9SLisandro Dalcin 
1106698a79b9SLisandro Dalcin   PetscFunctionBegin;
11079566063dSJacob Faibussowitsch   PetscCall(GmshReadString(gmsh, line, 1));
1108a45dabc8SMatthew G. Knepley   snum = sscanf(line, "%d", &region);
1109a45dabc8SMatthew G. Knepley   mesh->numRegions = region;
111008401ef6SPierre Jolivet   PetscCheck(snum == 1,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
11119566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(mesh->numRegions, &mesh->regionTags, mesh->numRegions, &mesh->regionNames));
1112a45dabc8SMatthew G. Knepley   for (region = 0; region < mesh->numRegions; ++region) {
11139566063dSJacob Faibussowitsch     PetscCall(GmshReadString(gmsh, line, 2));
11141f643af3SLisandro Dalcin     snum = sscanf(line, "%d %d", &dim, &tag);
111508401ef6SPierre Jolivet     PetscCheck(snum == 2,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
11169566063dSJacob Faibussowitsch     PetscCall(GmshReadString(gmsh, line, -(PetscInt)sizeof(line)));
11179566063dSJacob Faibussowitsch     PetscCall(PetscStrchr(line, '"', &p));
111828b400f6SJacob Faibussowitsch     PetscCheck(p, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
11199566063dSJacob Faibussowitsch     PetscCall(PetscStrrchr(line, '"', &q));
112008401ef6SPierre Jolivet     PetscCheck(q != p, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
11215f5cd6d5SMatthew G. Knepley     PetscCall(PetscStrrchr(line, ':', &r));
11225f5cd6d5SMatthew G. Knepley     if (p != r) q = r;
11239566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(name, p+1, (size_t)(q-p-1)));
1124a45dabc8SMatthew G. Knepley     mesh->regionTags[region] = tag;
11259566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &mesh->regionNames[region]));
1126698a79b9SLisandro Dalcin   }
1127de78e4feSLisandro Dalcin   PetscFunctionReturn(0);
1128de78e4feSLisandro Dalcin }
1129de78e4feSLisandro Dalcin 
11300598e1a2SLisandro Dalcin static PetscErrorCode GmshReadEntities(GmshFile *gmsh, GmshMesh *mesh)
113196ca5757SLisandro Dalcin {
11320598e1a2SLisandro Dalcin   PetscFunctionBegin;
11330598e1a2SLisandro Dalcin   switch (gmsh->fileFormat) {
11349566063dSJacob Faibussowitsch   case 41: PetscCall(GmshReadEntities_v41(gmsh, mesh)); break;
11359566063dSJacob Faibussowitsch   default: PetscCall(GmshReadEntities_v40(gmsh, mesh)); break;
113696ca5757SLisandro Dalcin   }
11370598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
11380598e1a2SLisandro Dalcin }
11390598e1a2SLisandro Dalcin 
11400598e1a2SLisandro Dalcin static PetscErrorCode GmshReadNodes(GmshFile *gmsh, GmshMesh *mesh)
11410598e1a2SLisandro Dalcin {
11420598e1a2SLisandro Dalcin   PetscFunctionBegin;
11430598e1a2SLisandro Dalcin   switch (gmsh->fileFormat) {
11449566063dSJacob Faibussowitsch   case 41: PetscCall(GmshReadNodes_v41(gmsh, mesh)); break;
11459566063dSJacob Faibussowitsch   case 40: PetscCall(GmshReadNodes_v40(gmsh, mesh)); break;
11469566063dSJacob Faibussowitsch   default: PetscCall(GmshReadNodes_v22(gmsh, mesh)); break;
11470598e1a2SLisandro Dalcin   }
11480598e1a2SLisandro Dalcin 
11490598e1a2SLisandro Dalcin   { /* Gmsh v2.2/v4.0 does not provide min/max node tags */
11500598e1a2SLisandro Dalcin     if (mesh->numNodes > 0 && gmsh->nodeEnd >= gmsh->nodeStart) {
11510598e1a2SLisandro Dalcin       PetscInt  tagMin = PETSC_MAX_INT, tagMax = PETSC_MIN_INT, n;
11520598e1a2SLisandro Dalcin       GmshNodes *nodes = mesh->nodelist;
11530598e1a2SLisandro Dalcin       for (n = 0; n < mesh->numNodes; ++n) {
11540598e1a2SLisandro Dalcin         const PetscInt tag = nodes->id[n];
11550598e1a2SLisandro Dalcin         tagMin = PetscMin(tag, tagMin);
11560598e1a2SLisandro Dalcin         tagMax = PetscMax(tag, tagMax);
11570598e1a2SLisandro Dalcin       }
11580598e1a2SLisandro Dalcin       gmsh->nodeStart = tagMin;
11590598e1a2SLisandro Dalcin       gmsh->nodeEnd   = tagMax+1;
11600598e1a2SLisandro Dalcin     }
11610598e1a2SLisandro Dalcin   }
11620598e1a2SLisandro Dalcin 
11630598e1a2SLisandro Dalcin   { /* Support for sparse node tags */
11640598e1a2SLisandro Dalcin     PetscInt  n, t;
11650598e1a2SLisandro Dalcin     GmshNodes *nodes = mesh->nodelist;
11669566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(gmsh->nodeEnd - gmsh->nodeStart, &gmsh->nbuf));
11670598e1a2SLisandro Dalcin     for (t = 0; t < gmsh->nodeEnd - gmsh->nodeStart; ++t) gmsh->nbuf[t] = PETSC_MIN_INT;
11680598e1a2SLisandro Dalcin     gmsh->nodeMap = gmsh->nbuf - gmsh->nodeStart;
11690598e1a2SLisandro Dalcin     for (n = 0; n < mesh->numNodes; ++n) {
11700598e1a2SLisandro Dalcin       const PetscInt tag = nodes->id[n];
117108401ef6SPierre Jolivet       PetscCheck(gmsh->nodeMap[tag] < 0,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Repeated node tag %D", tag);
11720598e1a2SLisandro Dalcin       gmsh->nodeMap[tag] = n;
11730598e1a2SLisandro Dalcin     }
11740598e1a2SLisandro Dalcin   }
11750598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
11760598e1a2SLisandro Dalcin }
11770598e1a2SLisandro Dalcin 
11780598e1a2SLisandro Dalcin static PetscErrorCode GmshReadElements(GmshFile *gmsh, GmshMesh *mesh)
11790598e1a2SLisandro Dalcin {
11800598e1a2SLisandro Dalcin   PetscFunctionBegin;
11810598e1a2SLisandro Dalcin   switch (gmsh->fileFormat) {
11829566063dSJacob Faibussowitsch   case 41: PetscCall(GmshReadElements_v41(gmsh, mesh)); break;
11839566063dSJacob Faibussowitsch   case 40: PetscCall(GmshReadElements_v40(gmsh, mesh)); break;
11849566063dSJacob Faibussowitsch   default: PetscCall(GmshReadElements_v22(gmsh, mesh)); break;
11850598e1a2SLisandro Dalcin   }
11860598e1a2SLisandro Dalcin 
11870598e1a2SLisandro Dalcin   { /* Reorder elements by codimension and polytope type */
11880598e1a2SLisandro Dalcin     PetscInt    ne = mesh->numElems;
11890598e1a2SLisandro Dalcin     GmshElement *elements = mesh->elements;
1190066ea43fSLisandro Dalcin     PetscInt    keymap[GMSH_NUM_POLYTOPES], nk = 0;
1191066ea43fSLisandro Dalcin     PetscInt    offset[GMSH_NUM_POLYTOPES+1], e, k;
11920598e1a2SLisandro Dalcin 
1193066ea43fSLisandro Dalcin     for (k = 0; k < GMSH_NUM_POLYTOPES; ++k) keymap[k] = PETSC_MIN_INT;
11949566063dSJacob Faibussowitsch     PetscCall(PetscMemzero(offset,sizeof(offset)));
11950598e1a2SLisandro Dalcin 
1196066ea43fSLisandro Dalcin     keymap[GMSH_TET] = nk++;
1197066ea43fSLisandro Dalcin     keymap[GMSH_HEX] = nk++;
1198066ea43fSLisandro Dalcin     keymap[GMSH_PRI] = nk++;
1199066ea43fSLisandro Dalcin     keymap[GMSH_PYR] = nk++;
1200066ea43fSLisandro Dalcin     keymap[GMSH_TRI] = nk++;
1201066ea43fSLisandro Dalcin     keymap[GMSH_QUA] = nk++;
1202066ea43fSLisandro Dalcin     keymap[GMSH_SEG] = nk++;
1203066ea43fSLisandro Dalcin     keymap[GMSH_VTX] = nk++;
12040598e1a2SLisandro Dalcin 
12059566063dSJacob Faibussowitsch     PetscCall(GmshElementsCreate(mesh->numElems, &mesh->elements));
12060598e1a2SLisandro Dalcin #define key(eid) keymap[GmshCellMap[elements[(eid)].cellType].polytope]
12070598e1a2SLisandro Dalcin     for (e = 0; e < ne; ++e) offset[1+key(e)]++;
12080598e1a2SLisandro Dalcin     for (k = 1; k < nk; ++k) offset[k] += offset[k-1];
12090598e1a2SLisandro Dalcin     for (e = 0; e < ne; ++e) mesh->elements[offset[key(e)]++] = elements[e];
12100598e1a2SLisandro Dalcin #undef key
12119566063dSJacob Faibussowitsch     PetscCall(GmshElementsDestroy(&elements));
1212066ea43fSLisandro Dalcin   }
12130598e1a2SLisandro Dalcin 
1214066ea43fSLisandro Dalcin   { /* Mesh dimension and order */
1215066ea43fSLisandro Dalcin     GmshElement *elem = mesh->numElems ? mesh->elements : NULL;
1216066ea43fSLisandro Dalcin     mesh->dim   = elem ? GmshCellMap[elem->cellType].dim   : 0;
1217066ea43fSLisandro Dalcin     mesh->order = elem ? GmshCellMap[elem->cellType].order : 0;
12180598e1a2SLisandro Dalcin   }
12190598e1a2SLisandro Dalcin 
12200598e1a2SLisandro Dalcin   {
12210598e1a2SLisandro Dalcin     PetscBT  vtx;
12220598e1a2SLisandro Dalcin     PetscInt dim = mesh->dim, e, n, v;
12230598e1a2SLisandro Dalcin 
12249566063dSJacob Faibussowitsch     PetscCall(PetscBTCreate(mesh->numNodes, &vtx));
12250598e1a2SLisandro Dalcin 
12260598e1a2SLisandro Dalcin     /* Compute number of cells and set of vertices */
12270598e1a2SLisandro Dalcin     mesh->numCells = 0;
12280598e1a2SLisandro Dalcin     for (e = 0; e < mesh->numElems; ++e) {
12290598e1a2SLisandro Dalcin       GmshElement *elem = mesh->elements + e;
12300598e1a2SLisandro Dalcin       if (elem->dim == dim && dim > 0) mesh->numCells++;
12310598e1a2SLisandro Dalcin       for (v = 0; v < elem->numVerts; v++) {
12329566063dSJacob Faibussowitsch         PetscCall(PetscBTSet(vtx, elem->nodes[v]));
12330598e1a2SLisandro Dalcin       }
12340598e1a2SLisandro Dalcin     }
12350598e1a2SLisandro Dalcin 
12360598e1a2SLisandro Dalcin     /* Compute numbering for vertices */
12370598e1a2SLisandro Dalcin     mesh->numVerts = 0;
12389566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(mesh->numNodes, &mesh->vertexMap));
12390598e1a2SLisandro Dalcin     for (n = 0; n < mesh->numNodes; ++n)
12400598e1a2SLisandro Dalcin       mesh->vertexMap[n] = PetscBTLookup(vtx, n) ? mesh->numVerts++ : PETSC_MIN_INT;
12410598e1a2SLisandro Dalcin 
12429566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&vtx));
12430598e1a2SLisandro Dalcin   }
12440598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
12450598e1a2SLisandro Dalcin }
12460598e1a2SLisandro Dalcin 
12470598e1a2SLisandro Dalcin static PetscErrorCode GmshReadPeriodic(GmshFile *gmsh, GmshMesh *mesh)
12480598e1a2SLisandro Dalcin {
12490598e1a2SLisandro Dalcin   PetscInt       n;
12500598e1a2SLisandro Dalcin 
12510598e1a2SLisandro Dalcin   PetscFunctionBegin;
12529566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(mesh->numNodes, &mesh->periodMap));
12530598e1a2SLisandro Dalcin   for (n = 0; n < mesh->numNodes; ++n) mesh->periodMap[n] = n;
12540598e1a2SLisandro Dalcin   switch (gmsh->fileFormat) {
12559566063dSJacob Faibussowitsch   case 41: PetscCall(GmshReadPeriodic_v41(gmsh, mesh->periodMap)); break;
12569566063dSJacob Faibussowitsch   default: PetscCall(GmshReadPeriodic_v40(gmsh, mesh->periodMap)); break;
12570598e1a2SLisandro Dalcin   }
12580598e1a2SLisandro Dalcin 
12599dddd249SSatish Balay   /* Find canonical primary nodes */
12600598e1a2SLisandro Dalcin   for (n = 0; n < mesh->numNodes; ++n)
12610598e1a2SLisandro Dalcin     while (mesh->periodMap[n] != mesh->periodMap[mesh->periodMap[n]])
12620598e1a2SLisandro Dalcin       mesh->periodMap[n] = mesh->periodMap[mesh->periodMap[n]];
12630598e1a2SLisandro Dalcin 
12649dddd249SSatish Balay   /* Renumber vertices (filter out correspondings) */
12650598e1a2SLisandro Dalcin   mesh->numVerts = 0;
12660598e1a2SLisandro Dalcin   for (n = 0; n < mesh->numNodes; ++n)
12670598e1a2SLisandro Dalcin     if (mesh->vertexMap[n] >= 0)   /* is vertex */
12689dddd249SSatish Balay       if (mesh->periodMap[n] == n) /* is primary */
12690598e1a2SLisandro Dalcin         mesh->vertexMap[n] = mesh->numVerts++;
12700598e1a2SLisandro Dalcin   for (n = 0; n < mesh->numNodes; ++n)
12710598e1a2SLisandro Dalcin     if (mesh->vertexMap[n] >= 0)   /* is vertex */
12729dddd249SSatish Balay       if (mesh->periodMap[n] != n) /* is corresponding  */
12730598e1a2SLisandro Dalcin         mesh->vertexMap[n] = mesh->vertexMap[mesh->periodMap[n]];
12740598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
12750598e1a2SLisandro Dalcin }
12760598e1a2SLisandro Dalcin 
1277066ea43fSLisandro Dalcin #define DM_POLYTOPE_VERTEX  DM_POLYTOPE_POINT
1278066ea43fSLisandro Dalcin #define DM_POLYTOPE_PYRAMID DM_POLYTOPE_UNKNOWN
1279066ea43fSLisandro Dalcin static const DMPolytopeType DMPolytopeMap[] = {
1280066ea43fSLisandro Dalcin   /* GMSH_VTX */ DM_POLYTOPE_VERTEX,
1281066ea43fSLisandro Dalcin   /* GMSH_SEG */ DM_POLYTOPE_SEGMENT,
1282066ea43fSLisandro Dalcin   /* GMSH_TRI */ DM_POLYTOPE_TRIANGLE,
1283066ea43fSLisandro Dalcin   /* GMSH_QUA */ DM_POLYTOPE_QUADRILATERAL,
1284066ea43fSLisandro Dalcin   /* GMSH_TET */ DM_POLYTOPE_TETRAHEDRON,
1285066ea43fSLisandro Dalcin   /* GMSH_HEX */ DM_POLYTOPE_HEXAHEDRON,
1286066ea43fSLisandro Dalcin   /* GMSH_PRI */ DM_POLYTOPE_TRI_PRISM,
1287066ea43fSLisandro Dalcin   /* GMSH_PYR */ DM_POLYTOPE_PYRAMID,
1288066ea43fSLisandro Dalcin   DM_POLYTOPE_UNKNOWN
1289066ea43fSLisandro Dalcin };
12900598e1a2SLisandro Dalcin 
12919fbee547SJacob Faibussowitsch static inline DMPolytopeType DMPolytopeTypeFromGmsh(PetscInt cellType)
12920598e1a2SLisandro Dalcin {
1293066ea43fSLisandro Dalcin   return DMPolytopeMap[GmshCellMap[cellType].polytope];
1294066ea43fSLisandro Dalcin }
1295066ea43fSLisandro Dalcin 
1296066ea43fSLisandro Dalcin static PetscErrorCode GmshCreateFE(MPI_Comm comm, const char prefix[], PetscBool isSimplex, PetscBool continuity, PetscDTNodeType nodeType, PetscInt dim, PetscInt Nc, PetscInt k, PetscFE *fem)
1297066ea43fSLisandro Dalcin {
1298066ea43fSLisandro Dalcin   DM              K;
1299066ea43fSLisandro Dalcin   PetscSpace      P;
1300066ea43fSLisandro Dalcin   PetscDualSpace  Q;
1301066ea43fSLisandro Dalcin   PetscQuadrature q, fq;
1302066ea43fSLisandro Dalcin   PetscBool       isTensor = isSimplex ? PETSC_FALSE : PETSC_TRUE;
1303066ea43fSLisandro Dalcin   PetscBool       endpoint = PETSC_TRUE;
1304066ea43fSLisandro Dalcin   char            name[32];
1305066ea43fSLisandro Dalcin 
1306066ea43fSLisandro Dalcin   PetscFunctionBegin;
1307066ea43fSLisandro Dalcin   /* Create space */
13089566063dSJacob Faibussowitsch   PetscCall(PetscSpaceCreate(comm, &P));
13099566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSetType(P, PETSCSPACEPOLYNOMIAL));
13109566063dSJacob Faibussowitsch   PetscCall(PetscSpacePolynomialSetTensor(P, isTensor));
13119566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSetNumComponents(P, Nc));
13129566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSetNumVariables(P, dim));
13139566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSetDegree(P, k, PETSC_DETERMINE));
1314066ea43fSLisandro Dalcin   if (prefix) {
13159566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject) P, prefix));
13169566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetFromOptions(P));
13179566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject) P, NULL));
13189566063dSJacob Faibussowitsch     PetscCall(PetscSpaceGetDegree(P, &k, NULL));
1319066ea43fSLisandro Dalcin   }
13209566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSetUp(P));
1321066ea43fSLisandro Dalcin   /* Create dual space */
13229566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceCreate(comm, &Q));
13239566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSetType(Q, PETSCDUALSPACELAGRANGE));
13249566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceLagrangeSetTensor(Q, isTensor));
13259566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceLagrangeSetContinuity(Q, continuity));
13269566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceLagrangeSetNodeType(Q, nodeType, endpoint, 0));
13279566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSetNumComponents(Q, Nc));
13289566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSetOrder(Q, k));
13299566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateReferenceCell(PETSC_COMM_SELF, DMPolytopeTypeSimpleShape(dim, isSimplex), &K));
13309566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSetDM(Q, K));
13319566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&K));
1332066ea43fSLisandro Dalcin   if (prefix) {
13339566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject) Q, prefix));
13349566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceSetFromOptions(Q));
13359566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject) Q, NULL));
1336066ea43fSLisandro Dalcin   }
13379566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSetUp(Q));
1338066ea43fSLisandro Dalcin   /* Create quadrature */
1339066ea43fSLisandro Dalcin   if (isSimplex) {
13409566063dSJacob Faibussowitsch     PetscCall(PetscDTStroudConicalQuadrature(dim,   1, k+1, -1, +1, &q));
13419566063dSJacob Faibussowitsch     PetscCall(PetscDTStroudConicalQuadrature(dim-1, 1, k+1, -1, +1, &fq));
1342066ea43fSLisandro Dalcin   } else {
13439566063dSJacob Faibussowitsch     PetscCall(PetscDTGaussTensorQuadrature(dim,   1, k+1, -1, +1, &q));
13449566063dSJacob Faibussowitsch     PetscCall(PetscDTGaussTensorQuadrature(dim-1, 1, k+1, -1, +1, &fq));
1345066ea43fSLisandro Dalcin   }
1346066ea43fSLisandro Dalcin   /* Create finite element */
13479566063dSJacob Faibussowitsch   PetscCall(PetscFECreate(comm, fem));
13489566063dSJacob Faibussowitsch   PetscCall(PetscFESetType(*fem, PETSCFEBASIC));
13499566063dSJacob Faibussowitsch   PetscCall(PetscFESetNumComponents(*fem, Nc));
13509566063dSJacob Faibussowitsch   PetscCall(PetscFESetBasisSpace(*fem, P));
13519566063dSJacob Faibussowitsch   PetscCall(PetscFESetDualSpace(*fem, Q));
13529566063dSJacob Faibussowitsch   PetscCall(PetscFESetQuadrature(*fem, q));
13539566063dSJacob Faibussowitsch   PetscCall(PetscFESetFaceQuadrature(*fem, fq));
1354066ea43fSLisandro Dalcin   if (prefix) {
13559566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject) *fem, prefix));
13569566063dSJacob Faibussowitsch     PetscCall(PetscFESetFromOptions(*fem));
13579566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject) *fem, NULL));
1358066ea43fSLisandro Dalcin   }
13599566063dSJacob Faibussowitsch   PetscCall(PetscFESetUp(*fem));
1360066ea43fSLisandro Dalcin   /* Cleanup */
13619566063dSJacob Faibussowitsch   PetscCall(PetscSpaceDestroy(&P));
13629566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceDestroy(&Q));
13639566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureDestroy(&q));
13649566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureDestroy(&fq));
1365066ea43fSLisandro Dalcin   /* Set finite element name */
13669566063dSJacob Faibussowitsch   PetscCall(PetscSNPrintf(name, sizeof(name), "%s%D", isSimplex? "P" : "Q", k));
13679566063dSJacob Faibussowitsch   PetscCall(PetscFESetName(*fem, name));
1368066ea43fSLisandro Dalcin   PetscFunctionReturn(0);
136996ca5757SLisandro Dalcin }
137096ca5757SLisandro Dalcin 
1371d6689ca9SLisandro Dalcin /*@C
1372d6689ca9SLisandro Dalcin   DMPlexCreateGmshFromFile - Create a DMPlex mesh from a Gmsh file
1373d6689ca9SLisandro Dalcin 
1374d6689ca9SLisandro Dalcin + comm        - The MPI communicator
1375d6689ca9SLisandro Dalcin . filename    - Name of the Gmsh file
1376d6689ca9SLisandro Dalcin - interpolate - Create faces and edges in the mesh
1377d6689ca9SLisandro Dalcin 
1378d6689ca9SLisandro Dalcin   Output Parameter:
1379d6689ca9SLisandro Dalcin . dm  - The DM object representing the mesh
1380d6689ca9SLisandro Dalcin 
1381d6689ca9SLisandro Dalcin   Level: beginner
1382d6689ca9SLisandro Dalcin 
1383d6689ca9SLisandro Dalcin .seealso: DMPlexCreateFromFile(), DMPlexCreateGmsh(), DMPlexCreate()
1384d6689ca9SLisandro Dalcin @*/
1385d6689ca9SLisandro Dalcin PetscErrorCode DMPlexCreateGmshFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm)
1386d6689ca9SLisandro Dalcin {
1387d6689ca9SLisandro Dalcin   PetscViewer     viewer;
1388d6689ca9SLisandro Dalcin   PetscMPIInt     rank;
1389d6689ca9SLisandro Dalcin   int             fileType;
1390d6689ca9SLisandro Dalcin   PetscViewerType vtype;
1391d6689ca9SLisandro Dalcin 
1392d6689ca9SLisandro Dalcin   PetscFunctionBegin;
13939566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1394d6689ca9SLisandro Dalcin 
1395d6689ca9SLisandro Dalcin   /* Determine Gmsh file type (ASCII or binary) from file header */
1396dd400576SPatrick Sanan   if (rank == 0) {
13970598e1a2SLisandro Dalcin     GmshFile    gmsh[1];
1398d6689ca9SLisandro Dalcin     char        line[PETSC_MAX_PATH_LEN];
1399d6689ca9SLisandro Dalcin     int         snum;
1400d6689ca9SLisandro Dalcin     float       version;
1401d6689ca9SLisandro Dalcin 
14029566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(gmsh,1));
14039566063dSJacob Faibussowitsch     PetscCall(PetscViewerCreate(PETSC_COMM_SELF, &gmsh->viewer));
14049566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetType(gmsh->viewer, PETSCVIEWERASCII));
14059566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileSetMode(gmsh->viewer, FILE_MODE_READ));
14069566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileSetName(gmsh->viewer, filename));
1407d6689ca9SLisandro Dalcin     /* Read only the first two lines of the Gmsh file */
14089566063dSJacob Faibussowitsch     PetscCall(GmshReadSection(gmsh, line));
14099566063dSJacob Faibussowitsch     PetscCall(GmshExpect(gmsh, "$MeshFormat", line));
14109566063dSJacob Faibussowitsch     PetscCall(GmshReadString(gmsh, line, 2));
1411d6689ca9SLisandro Dalcin     snum = sscanf(line, "%f %d", &version, &fileType);
141208401ef6SPierre Jolivet     PetscCheck(snum == 2,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line);
141308401ef6SPierre Jolivet     PetscCheck(version >= 2.2,PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at least 2.2", (double)version);
14142c71b3e2SJacob Faibussowitsch     PetscCheckFalse((int)version == 3,PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f not supported", (double)version);
141508401ef6SPierre Jolivet     PetscCheck(version <= 4.1,PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at most 4.1", (double)version);
14169566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&gmsh->viewer));
1417d6689ca9SLisandro Dalcin   }
14189566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&fileType, 1, MPI_INT, 0, comm));
1419d6689ca9SLisandro Dalcin   vtype = (fileType == 0) ? PETSCVIEWERASCII : PETSCVIEWERBINARY;
1420d6689ca9SLisandro Dalcin 
1421d6689ca9SLisandro Dalcin   /* Create appropriate viewer and build plex */
14229566063dSJacob Faibussowitsch   PetscCall(PetscViewerCreate(comm, &viewer));
14239566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetType(viewer, vtype));
14249566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
14259566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetName(viewer, filename));
14269566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateGmsh(comm, viewer, interpolate, dm));
14279566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&viewer));
1428d6689ca9SLisandro Dalcin   PetscFunctionReturn(0);
1429d6689ca9SLisandro Dalcin }
1430d6689ca9SLisandro Dalcin 
1431331830f3SMatthew G. Knepley /*@
14327d282ae0SMichael Lange   DMPlexCreateGmsh - Create a DMPlex mesh from a Gmsh file viewer
1433331830f3SMatthew G. Knepley 
1434d083f849SBarry Smith   Collective
1435331830f3SMatthew G. Knepley 
1436331830f3SMatthew G. Knepley   Input Parameters:
1437331830f3SMatthew G. Knepley + comm  - The MPI communicator
1438331830f3SMatthew G. Knepley . viewer - The Viewer associated with a Gmsh file
1439331830f3SMatthew G. Knepley - interpolate - Create faces and edges in the mesh
1440331830f3SMatthew G. Knepley 
1441331830f3SMatthew G. Knepley   Output Parameter:
1442331830f3SMatthew G. Knepley . dm  - The DM object representing the mesh
1443331830f3SMatthew G. Knepley 
1444698a79b9SLisandro Dalcin   Note: http://gmsh.info/doc/texinfo/gmsh.html#MSH-file-format
1445331830f3SMatthew G. Knepley 
1446331830f3SMatthew G. Knepley   Level: beginner
1447331830f3SMatthew G. Knepley 
1448331830f3SMatthew G. Knepley .seealso: DMPLEX, DMCreate()
1449331830f3SMatthew G. Knepley @*/
1450331830f3SMatthew G. Knepley PetscErrorCode DMPlexCreateGmsh(MPI_Comm comm, PetscViewer viewer, PetscBool interpolate, DM *dm)
1451331830f3SMatthew G. Knepley {
14520598e1a2SLisandro Dalcin   GmshMesh      *mesh = NULL;
145311c56cb0SLisandro Dalcin   PetscViewer    parentviewer = NULL;
14540598e1a2SLisandro Dalcin   PetscBT        periodicVerts = NULL;
14550598e1a2SLisandro Dalcin   PetscBT        periodicCells = NULL;
1456066ea43fSLisandro Dalcin   DM             cdm;
1457331830f3SMatthew G. Knepley   PetscSection   coordSection;
1458331830f3SMatthew G. Knepley   Vec            coordinates;
1459a45dabc8SMatthew G. Knepley   DMLabel        cellSets = NULL, faceSets = NULL, vertSets = NULL, marker = NULL, *regionSets;
1460066ea43fSLisandro Dalcin   PetscInt       dim = 0, coordDim = -1, order = 0;
14610598e1a2SLisandro Dalcin   PetscInt       numNodes = 0, numElems = 0, numVerts = 0, numCells = 0;
1462066ea43fSLisandro Dalcin   PetscInt       cell, cone[8], e, n, v, d;
146381a1af93SMatthew G. Knepley   PetscBool      binary, usemarker = PETSC_FALSE, useregions = PETSC_FALSE, markvertices = PETSC_FALSE;
14640598e1a2SLisandro Dalcin   PetscBool      hybrid = interpolate, periodic = PETSC_TRUE;
1465066ea43fSLisandro Dalcin   PetscBool      highOrder = PETSC_TRUE, highOrderSet, project = PETSC_FALSE;
1466066ea43fSLisandro Dalcin   PetscBool      isSimplex = PETSC_FALSE, isHybrid = PETSC_FALSE, hasTetra = PETSC_FALSE;
14670598e1a2SLisandro Dalcin   PetscMPIInt    rank;
1468331830f3SMatthew G. Knepley 
1469331830f3SMatthew G. Knepley   PetscFunctionBegin;
14709566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1471d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)viewer);
1472d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject,"DMPlex Gmsh options");
14739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_gmsh_hybrid", "Generate hybrid cell bounds", "DMPlexCreateGmsh", hybrid, &hybrid, NULL));
14749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_gmsh_periodic","Read Gmsh periodic section", "DMPlexCreateGmsh", periodic, &periodic, NULL));
14759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_gmsh_highorder","Generate high-order coordinates", "DMPlexCreateGmsh", highOrder, &highOrder, &highOrderSet));
14769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_gmsh_project", "Project high-order coordinates to a different space", "DMPlexCreateGmsh", project, &project, NULL));
14779566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_gmsh_use_marker", "Generate marker label", "DMPlexCreateGmsh", usemarker, &usemarker, NULL));
14789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_gmsh_use_regions", "Generate labels with region names", "DMPlexCreateGmsh", useregions, &useregions, NULL));
14799566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_gmsh_mark_vertices", "Add vertices to generated labels", "DMPlexCreateGmsh", markvertices, &markvertices, NULL));
14809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_gmsh_spacedim", "Embedding space dimension", "DMPlexCreateGmsh", coordDim, &coordDim, NULL, PETSC_DECIDE));
1481d0609cedSBarry Smith   PetscOptionsHeadEnd();
1482d0609cedSBarry Smith   PetscOptionsEnd();
14830598e1a2SLisandro Dalcin 
14849566063dSJacob Faibussowitsch   PetscCall(GmshCellInfoSetUp());
148511c56cb0SLisandro Dalcin 
14869566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
14879566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
14889566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CreateGmsh,*dm,NULL,NULL,NULL));
148911c56cb0SLisandro Dalcin 
14909566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &binary));
149111c56cb0SLisandro Dalcin 
149211c56cb0SLisandro Dalcin   /* Binary viewers read on all ranks, get subviewer to read only in rank 0 */
14933b46f529SLisandro Dalcin   if (binary) {
149411c56cb0SLisandro Dalcin     parentviewer = viewer;
14959566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetSubViewer(parentviewer, PETSC_COMM_SELF, &viewer));
149611c56cb0SLisandro Dalcin   }
149711c56cb0SLisandro Dalcin 
1498dd400576SPatrick Sanan   if (rank == 0) {
14990598e1a2SLisandro Dalcin     GmshFile  gmsh[1];
1500698a79b9SLisandro Dalcin     char      line[PETSC_MAX_PATH_LEN];
1501698a79b9SLisandro Dalcin     PetscBool match;
1502331830f3SMatthew G. Knepley 
15039566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(gmsh,1));
1504698a79b9SLisandro Dalcin     gmsh->viewer = viewer;
1505698a79b9SLisandro Dalcin     gmsh->binary = binary;
1506698a79b9SLisandro Dalcin 
15079566063dSJacob Faibussowitsch     PetscCall(GmshMeshCreate(&mesh));
15080598e1a2SLisandro Dalcin 
1509698a79b9SLisandro Dalcin     /* Read mesh format */
15109566063dSJacob Faibussowitsch     PetscCall(GmshReadSection(gmsh, line));
15119566063dSJacob Faibussowitsch     PetscCall(GmshExpect(gmsh, "$MeshFormat", line));
15129566063dSJacob Faibussowitsch     PetscCall(GmshReadMeshFormat(gmsh));
15139566063dSJacob Faibussowitsch     PetscCall(GmshReadEndSection(gmsh, "$EndMeshFormat", line));
151411c56cb0SLisandro Dalcin 
1515dc0ede3bSMatthew G. Knepley     /* OPTIONAL Read physical names */
15169566063dSJacob Faibussowitsch     PetscCall(GmshReadSection(gmsh, line));
15179566063dSJacob Faibussowitsch     PetscCall(GmshMatch(gmsh, "$PhysicalNames", line, &match));
1518dc0ede3bSMatthew G. Knepley     if (match) {
15199566063dSJacob Faibussowitsch       PetscCall(GmshExpect(gmsh, "$PhysicalNames", line));
15209566063dSJacob Faibussowitsch       PetscCall(GmshReadPhysicalNames(gmsh, mesh));
15219566063dSJacob Faibussowitsch       PetscCall(GmshReadEndSection(gmsh, "$EndPhysicalNames", line));
1522698a79b9SLisandro Dalcin       /* Initial read for entity section */
15239566063dSJacob Faibussowitsch       PetscCall(GmshReadSection(gmsh, line));
1524dc0ede3bSMatthew G. Knepley     }
152511c56cb0SLisandro Dalcin 
1526de78e4feSLisandro Dalcin     /* Read entities */
1527698a79b9SLisandro Dalcin     if (gmsh->fileFormat >= 40) {
15289566063dSJacob Faibussowitsch       PetscCall(GmshExpect(gmsh, "$Entities", line));
15299566063dSJacob Faibussowitsch       PetscCall(GmshReadEntities(gmsh, mesh));
15309566063dSJacob Faibussowitsch       PetscCall(GmshReadEndSection(gmsh, "$EndEntities", line));
1531698a79b9SLisandro Dalcin       /* Initial read for nodes section */
15329566063dSJacob Faibussowitsch       PetscCall(GmshReadSection(gmsh, line));
1533de78e4feSLisandro Dalcin     }
1534de78e4feSLisandro Dalcin 
1535698a79b9SLisandro Dalcin     /* Read nodes */
15369566063dSJacob Faibussowitsch     PetscCall(GmshExpect(gmsh, "$Nodes", line));
15379566063dSJacob Faibussowitsch     PetscCall(GmshReadNodes(gmsh, mesh));
15389566063dSJacob Faibussowitsch     PetscCall(GmshReadEndSection(gmsh, "$EndNodes", line));
153911c56cb0SLisandro Dalcin 
1540698a79b9SLisandro Dalcin     /* Read elements */
15419566063dSJacob Faibussowitsch     PetscCall(GmshReadSection(gmsh, line));
15429566063dSJacob Faibussowitsch     PetscCall(GmshExpect(gmsh, "$Elements", line));
15439566063dSJacob Faibussowitsch     PetscCall(GmshReadElements(gmsh, mesh));
15449566063dSJacob Faibussowitsch     PetscCall(GmshReadEndSection(gmsh, "$EndElements", line));
1545de78e4feSLisandro Dalcin 
15460598e1a2SLisandro Dalcin     /* Read periodic section (OPTIONAL) */
1547698a79b9SLisandro Dalcin     if (periodic) {
15489566063dSJacob Faibussowitsch       PetscCall(GmshReadSection(gmsh, line));
15499566063dSJacob Faibussowitsch       PetscCall(GmshMatch(gmsh, "$Periodic", line, &periodic));
1550ef12879bSLisandro Dalcin     }
1551ef12879bSLisandro Dalcin     if (periodic) {
15529566063dSJacob Faibussowitsch       PetscCall(GmshExpect(gmsh, "$Periodic", line));
15539566063dSJacob Faibussowitsch       PetscCall(GmshReadPeriodic(gmsh, mesh));
15549566063dSJacob Faibussowitsch       PetscCall(GmshReadEndSection(gmsh, "$EndPeriodic", line));
1555698a79b9SLisandro Dalcin     }
1556698a79b9SLisandro Dalcin 
15579566063dSJacob Faibussowitsch     PetscCall(PetscFree(gmsh->wbuf));
15589566063dSJacob Faibussowitsch     PetscCall(PetscFree(gmsh->sbuf));
15599566063dSJacob Faibussowitsch     PetscCall(PetscFree(gmsh->nbuf));
15600598e1a2SLisandro Dalcin 
15610598e1a2SLisandro Dalcin     dim       = mesh->dim;
1562066ea43fSLisandro Dalcin     order     = mesh->order;
15630598e1a2SLisandro Dalcin     numNodes  = mesh->numNodes;
15640598e1a2SLisandro Dalcin     numElems  = mesh->numElems;
15650598e1a2SLisandro Dalcin     numVerts  = mesh->numVerts;
15660598e1a2SLisandro Dalcin     numCells  = mesh->numCells;
1567066ea43fSLisandro Dalcin 
1568066ea43fSLisandro Dalcin     {
1569066ea43fSLisandro Dalcin       GmshElement *elemA = mesh->numCells > 0 ? mesh->elements : NULL;
1570066ea43fSLisandro Dalcin       GmshElement *elemB = elemA ? elemA + mesh->numCells - 1  : NULL;
1571066ea43fSLisandro Dalcin       int ptA = elemA ? GmshCellMap[elemA->cellType].polytope : -1;
1572066ea43fSLisandro Dalcin       int ptB = elemB ? GmshCellMap[elemB->cellType].polytope : -1;
1573066ea43fSLisandro Dalcin       isSimplex = (ptA == GMSH_QUA || ptA == GMSH_HEX) ? PETSC_FALSE : PETSC_TRUE;
1574066ea43fSLisandro Dalcin       isHybrid  = (ptA == ptB) ? PETSC_FALSE : PETSC_TRUE;
1575066ea43fSLisandro Dalcin       hasTetra  = (ptA == GMSH_TET) ? PETSC_TRUE : PETSC_FALSE;
1576066ea43fSLisandro Dalcin     }
1577698a79b9SLisandro Dalcin   }
1578698a79b9SLisandro Dalcin 
1579698a79b9SLisandro Dalcin   if (parentviewer) {
15809566063dSJacob Faibussowitsch     PetscCall(PetscViewerRestoreSubViewer(parentviewer, PETSC_COMM_SELF, &viewer));
1581698a79b9SLisandro Dalcin   }
1582698a79b9SLisandro Dalcin 
1583066ea43fSLisandro Dalcin   {
1584066ea43fSLisandro Dalcin     int buf[6];
1585698a79b9SLisandro Dalcin 
1586066ea43fSLisandro Dalcin     buf[0] = (int)dim;
1587066ea43fSLisandro Dalcin     buf[1] = (int)order;
1588066ea43fSLisandro Dalcin     buf[2] = periodic;
1589066ea43fSLisandro Dalcin     buf[3] = isSimplex;
1590066ea43fSLisandro Dalcin     buf[4] = isHybrid;
1591066ea43fSLisandro Dalcin     buf[5] = hasTetra;
1592066ea43fSLisandro Dalcin 
15939566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Bcast(buf, 6, MPI_INT, 0, comm));
1594066ea43fSLisandro Dalcin 
1595066ea43fSLisandro Dalcin     dim       = buf[0];
1596066ea43fSLisandro Dalcin     order     = buf[1];
1597066ea43fSLisandro Dalcin     periodic  = buf[2] ? PETSC_TRUE : PETSC_FALSE;
1598066ea43fSLisandro Dalcin     isSimplex = buf[3] ? PETSC_TRUE : PETSC_FALSE;
1599066ea43fSLisandro Dalcin     isHybrid  = buf[4] ? PETSC_TRUE : PETSC_FALSE;
1600066ea43fSLisandro Dalcin     hasTetra  = buf[5] ? PETSC_TRUE : PETSC_FALSE;
1601dea2a3c7SStefano Zampini   }
1602dea2a3c7SStefano Zampini 
1603066ea43fSLisandro Dalcin   if (!highOrderSet) highOrder = (order > 1) ? PETSC_TRUE : PETSC_FALSE;
160408401ef6SPierre Jolivet   PetscCheck(!highOrder || !isHybrid,comm, PETSC_ERR_SUP, "No support for discretization on hybrid meshes yet");
1605066ea43fSLisandro Dalcin 
16060598e1a2SLisandro Dalcin   /* We do not want this label automatically computed, instead we fill it here */
16079566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(*dm, "celltype"));
160811c56cb0SLisandro Dalcin 
1609a4bb7517SMichael Lange   /* Allocate the cell-vertex mesh */
16109566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(*dm, 0, numCells+numVerts));
16110598e1a2SLisandro Dalcin   for (cell = 0; cell < numCells; ++cell) {
16120598e1a2SLisandro Dalcin     GmshElement *elem = mesh->elements + cell;
16130598e1a2SLisandro Dalcin     DMPolytopeType ctype = DMPolytopeTypeFromGmsh(elem->cellType);
16140598e1a2SLisandro Dalcin     if (hybrid && hasTetra && ctype == DM_POLYTOPE_TRI_PRISM) ctype = DM_POLYTOPE_TRI_PRISM_TENSOR;
16159566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeSize(*dm, cell, elem->numVerts));
16169566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCellType(*dm, cell, ctype));
1617db397164SMichael Lange   }
16180598e1a2SLisandro Dalcin   for (v = numCells; v < numCells+numVerts; ++v) {
16199566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCellType(*dm, v, DM_POLYTOPE_POINT));
162096ca5757SLisandro Dalcin   }
16219566063dSJacob Faibussowitsch   PetscCall(DMSetUp(*dm));
162296ca5757SLisandro Dalcin 
1623a4bb7517SMichael Lange   /* Add cell-vertex connections */
16240598e1a2SLisandro Dalcin   for (cell = 0; cell < numCells; ++cell) {
16250598e1a2SLisandro Dalcin     GmshElement *elem = mesh->elements + cell;
16260598e1a2SLisandro Dalcin     for (v = 0; v < elem->numVerts; ++v) {
16270598e1a2SLisandro Dalcin       const PetscInt nn = elem->nodes[v];
16280598e1a2SLisandro Dalcin       const PetscInt vv = mesh->vertexMap[nn];
16290598e1a2SLisandro Dalcin       cone[v] = numCells + vv;
1630db397164SMichael Lange     }
16319566063dSJacob Faibussowitsch     PetscCall(DMPlexReorderCell(*dm, cell, cone));
16329566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCone(*dm, cell, cone));
1633a4bb7517SMichael Lange   }
163496ca5757SLisandro Dalcin 
16359566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
16369566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(*dm));
16379566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(*dm));
1638331830f3SMatthew G. Knepley   if (interpolate) {
16395fd9971aSMatthew G. Knepley     DM idm;
1640331830f3SMatthew G. Knepley 
16419566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
16429566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
1643331830f3SMatthew G. Knepley     *dm  = idm;
1644331830f3SMatthew G. Knepley   }
1645917266a4SLisandro Dalcin 
164681a1af93SMatthew G. Knepley   /* Create the label "marker" over the whole boundary */
16472c71b3e2SJacob Faibussowitsch   PetscCheckFalse(usemarker && !interpolate && dim > 1,comm,PETSC_ERR_SUP,"Cannot create marker label without interpolation");
1648dd400576SPatrick Sanan   if (rank == 0 && usemarker) {
1649d3f73514SStefano Zampini     PetscInt f, fStart, fEnd;
1650d3f73514SStefano Zampini 
16519566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(*dm, "marker"));
16529566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(*dm, 1, &fStart, &fEnd));
1653d3f73514SStefano Zampini     for (f = fStart; f < fEnd; ++f) {
1654d3f73514SStefano Zampini       PetscInt suppSize;
1655d3f73514SStefano Zampini 
16569566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(*dm, f, &suppSize));
1657d3f73514SStefano Zampini       if (suppSize == 1) {
1658d3f73514SStefano Zampini         PetscInt *cone = NULL, coneSize, p;
1659d3f73514SStefano Zampini 
16609566063dSJacob Faibussowitsch         PetscCall(DMPlexGetTransitiveClosure(*dm, f, PETSC_TRUE, &coneSize, &cone));
1661d3f73514SStefano Zampini         for (p = 0; p < coneSize; p += 2) {
16629566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue_Fast(*dm, &marker, "marker", cone[p], 1));
1663d3f73514SStefano Zampini         }
16649566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreTransitiveClosure(*dm, f, PETSC_TRUE, &coneSize, &cone));
1665d3f73514SStefano Zampini       }
1666d3f73514SStefano Zampini     }
1667d3f73514SStefano Zampini   }
166816ad7e67SMichael Lange 
1669dd400576SPatrick Sanan   if (rank == 0) {
1670a45dabc8SMatthew G. Knepley     const PetscInt Nr = useregions ? mesh->numRegions : 0;
167111c56cb0SLisandro Dalcin     PetscInt       vStart, vEnd;
1672d1a54cefSMatthew G. Knepley 
16739566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(Nr, &regionSets));
16749566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(*dm, 0, &vStart, &vEnd));
16750598e1a2SLisandro Dalcin     for (cell = 0, e = 0; e < numElems; ++e) {
16760598e1a2SLisandro Dalcin       GmshElement *elem = mesh->elements + e;
16776e1dd89aSLawrence Mitchell 
16786e1dd89aSLawrence Mitchell       /* Create cell sets */
16790598e1a2SLisandro Dalcin       if (elem->dim == dim && dim > 0) {
16800598e1a2SLisandro Dalcin         if (elem->numTags > 0) {
1681a45dabc8SMatthew G. Knepley           const PetscInt tag = elem->tags[0];
1682a45dabc8SMatthew G. Knepley           PetscInt       r;
1683a45dabc8SMatthew G. Knepley 
16849566063dSJacob Faibussowitsch           if (!Nr) PetscCall(DMSetLabelValue_Fast(*dm, &cellSets, "Cell Sets", cell, tag));
1685a45dabc8SMatthew G. Knepley           for (r = 0; r < Nr; ++r) {
16869566063dSJacob Faibussowitsch             if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, &regionSets[r], mesh->regionNames[r], cell, tag));
1687a45dabc8SMatthew G. Knepley           }
16886e1dd89aSLawrence Mitchell         }
1689917266a4SLisandro Dalcin         cell++;
16906e1dd89aSLawrence Mitchell       }
16910c070f12SSander Arens 
16920598e1a2SLisandro Dalcin       /* Create face sets */
16930598e1a2SLisandro Dalcin       if (interpolate && elem->dim == dim-1) {
16940598e1a2SLisandro Dalcin         PetscInt        joinSize;
16950598e1a2SLisandro Dalcin         const PetscInt *join = NULL;
1696a45dabc8SMatthew G. Knepley         const PetscInt  tag = elem->tags[0];
1697a45dabc8SMatthew G. Knepley         PetscInt        r;
1698a45dabc8SMatthew G. Knepley 
16990598e1a2SLisandro Dalcin         /* Find the relevant facet with vertex joins */
17000598e1a2SLisandro Dalcin         for (v = 0; v < elem->numVerts; ++v) {
17010598e1a2SLisandro Dalcin           const PetscInt nn = elem->nodes[v];
17020598e1a2SLisandro Dalcin           const PetscInt vv = mesh->vertexMap[nn];
17030598e1a2SLisandro Dalcin           cone[v] = vStart + vv;
17040598e1a2SLisandro Dalcin         }
17059566063dSJacob Faibussowitsch         PetscCall(DMPlexGetFullJoin(*dm, elem->numVerts, cone, &joinSize, &join));
170608401ef6SPierre Jolivet         PetscCheck(joinSize == 1,PETSC_COMM_SELF, PETSC_ERR_SUP, "Could not determine Plex facet for Gmsh element %D (Plex cell %D)", elem->id, e);
17079566063dSJacob Faibussowitsch         if (!Nr) PetscCall(DMSetLabelValue_Fast(*dm, &faceSets, "Face Sets", join[0], tag));
1708a45dabc8SMatthew G. Knepley         for (r = 0; r < Nr; ++r) {
17099566063dSJacob Faibussowitsch           if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, &regionSets[r], mesh->regionNames[r], join[0], tag));
1710a45dabc8SMatthew G. Knepley         }
17119566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreJoin(*dm, elem->numVerts, cone, &joinSize, &join));
17120598e1a2SLisandro Dalcin       }
17130598e1a2SLisandro Dalcin 
17140c070f12SSander Arens       /* Create vertex sets */
17150598e1a2SLisandro Dalcin       if (elem->dim == 0) {
17160598e1a2SLisandro Dalcin         if (elem->numTags > 0) {
17170598e1a2SLisandro Dalcin           const PetscInt nn = elem->nodes[0];
17180598e1a2SLisandro Dalcin           const PetscInt vv = mesh->vertexMap[nn];
1719a45dabc8SMatthew G. Knepley           const PetscInt tag = elem->tags[0];
1720a45dabc8SMatthew G. Knepley           PetscInt       r;
1721a45dabc8SMatthew G. Knepley 
17229566063dSJacob Faibussowitsch           if (!Nr) PetscCall(DMSetLabelValue_Fast(*dm, &vertSets, "Vertex Sets", vStart + vv, tag));
172381a1af93SMatthew G. Knepley           for (r = 0; r < Nr; ++r) {
17249566063dSJacob Faibussowitsch             if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, &regionSets[r], mesh->regionNames[r], vStart + vv, tag));
172581a1af93SMatthew G. Knepley           }
172681a1af93SMatthew G. Knepley         }
172781a1af93SMatthew G. Knepley       }
172881a1af93SMatthew G. Knepley     }
172981a1af93SMatthew G. Knepley     if (markvertices) {
173081a1af93SMatthew G. Knepley       for (v = 0; v < numNodes; ++v) {
173181a1af93SMatthew G. Knepley         const PetscInt  vv   = mesh->vertexMap[v];
1732*7d5b9244SMatthew G. Knepley         const PetscInt *tags = &mesh->nodelist->tag[v*GMSH_MAX_TAGS];
1733*7d5b9244SMatthew G. Knepley         PetscInt        r, t;
173481a1af93SMatthew G. Knepley 
1735*7d5b9244SMatthew G. Knepley         for (t = 0; t < GMSH_MAX_TAGS; ++t) {
1736*7d5b9244SMatthew G. Knepley           const PetscInt tag = tags[t];
1737*7d5b9244SMatthew G. Knepley 
1738*7d5b9244SMatthew G. Knepley           if (tag == -1) continue;
17399566063dSJacob Faibussowitsch           if (!Nr) PetscCall(DMSetLabelValue_Fast(*dm, &vertSets, "Vertex Sets", vStart + vv, tag));
1740a45dabc8SMatthew G. Knepley           for (r = 0; r < Nr; ++r) {
17419566063dSJacob Faibussowitsch             if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, &regionSets[r], mesh->regionNames[r], vStart + vv, tag));
17420598e1a2SLisandro Dalcin           }
17430598e1a2SLisandro Dalcin         }
17440598e1a2SLisandro Dalcin       }
17450598e1a2SLisandro Dalcin     }
17469566063dSJacob Faibussowitsch     PetscCall(PetscFree(regionSets));
1747a45dabc8SMatthew G. Knepley   }
17480598e1a2SLisandro Dalcin 
17497dd454faSLisandro Dalcin   { /* Create Cell/Face/Vertex Sets labels at all processes */
17507dd454faSLisandro Dalcin     enum {n = 4};
17517dd454faSLisandro Dalcin     PetscBool flag[n];
17527dd454faSLisandro Dalcin 
17537dd454faSLisandro Dalcin     flag[0] = cellSets ? PETSC_TRUE : PETSC_FALSE;
17547dd454faSLisandro Dalcin     flag[1] = faceSets ? PETSC_TRUE : PETSC_FALSE;
17557dd454faSLisandro Dalcin     flag[2] = vertSets ? PETSC_TRUE : PETSC_FALSE;
17567dd454faSLisandro Dalcin     flag[3] = marker   ? PETSC_TRUE : PETSC_FALSE;
17579566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Bcast(flag, n, MPIU_BOOL, 0, comm));
17589566063dSJacob Faibussowitsch     if (flag[0]) PetscCall(DMCreateLabel(*dm, "Cell Sets"));
17599566063dSJacob Faibussowitsch     if (flag[1]) PetscCall(DMCreateLabel(*dm, "Face Sets"));
17609566063dSJacob Faibussowitsch     if (flag[2]) PetscCall(DMCreateLabel(*dm, "Vertex Sets"));
17619566063dSJacob Faibussowitsch     if (flag[3]) PetscCall(DMCreateLabel(*dm, "marker"));
17627dd454faSLisandro Dalcin   }
17637dd454faSLisandro Dalcin 
17640598e1a2SLisandro Dalcin   if (periodic) {
17659566063dSJacob Faibussowitsch     PetscCall(PetscBTCreate(numVerts, &periodicVerts));
17660598e1a2SLisandro Dalcin     for (n = 0; n < numNodes; ++n) {
17670598e1a2SLisandro Dalcin       if (mesh->vertexMap[n] >= 0) {
17680598e1a2SLisandro Dalcin         if (PetscUnlikely(mesh->periodMap[n] != n)) {
17690598e1a2SLisandro Dalcin           PetscInt m = mesh->periodMap[n];
17709566063dSJacob Faibussowitsch           PetscCall(PetscBTSet(periodicVerts, mesh->vertexMap[n]));
17719566063dSJacob Faibussowitsch           PetscCall(PetscBTSet(periodicVerts, mesh->vertexMap[m]));
17720598e1a2SLisandro Dalcin         }
17730598e1a2SLisandro Dalcin       }
17740598e1a2SLisandro Dalcin     }
17759566063dSJacob Faibussowitsch     PetscCall(PetscBTCreate(numCells, &periodicCells));
17760598e1a2SLisandro Dalcin     for (cell = 0; cell < numCells; ++cell) {
17770598e1a2SLisandro Dalcin       GmshElement *elem = mesh->elements + cell;
17780598e1a2SLisandro Dalcin       for (v = 0; v < elem->numVerts; ++v) {
17790598e1a2SLisandro Dalcin         PetscInt nn = elem->nodes[v];
17800598e1a2SLisandro Dalcin         PetscInt vv = mesh->vertexMap[nn];
17810598e1a2SLisandro Dalcin         if (PetscUnlikely(PetscBTLookup(periodicVerts, vv))) {
17829566063dSJacob Faibussowitsch           PetscCall(PetscBTSet(periodicCells, cell)); break;
17830c070f12SSander Arens         }
17840c070f12SSander Arens       }
17850c070f12SSander Arens     }
178616ad7e67SMichael Lange   }
178716ad7e67SMichael Lange 
1788066ea43fSLisandro Dalcin   /* Setup coordinate DM */
17890598e1a2SLisandro Dalcin   if (coordDim < 0) coordDim = dim;
17909566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(*dm, coordDim));
17919566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(*dm, &cdm));
1792066ea43fSLisandro Dalcin   if (highOrder) {
1793066ea43fSLisandro Dalcin     PetscFE         fe;
1794066ea43fSLisandro Dalcin     PetscBool       continuity = periodic ? PETSC_FALSE : PETSC_TRUE;
1795066ea43fSLisandro Dalcin     PetscDTNodeType nodeType   = PETSCDTNODES_EQUISPACED;
1796066ea43fSLisandro Dalcin 
1797066ea43fSLisandro Dalcin     if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */
1798066ea43fSLisandro Dalcin 
17999566063dSJacob Faibussowitsch     PetscCall(GmshCreateFE(comm, NULL, isSimplex, continuity, nodeType, dim, coordDim, order, &fe));
18009566063dSJacob Faibussowitsch     PetscCall(PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_fe_view"));
18019566063dSJacob Faibussowitsch     PetscCall(DMSetField(cdm, 0, NULL, (PetscObject) fe));
18029566063dSJacob Faibussowitsch     PetscCall(PetscFEDestroy(&fe));
18039566063dSJacob Faibussowitsch     PetscCall(DMCreateDS(cdm));
1804066ea43fSLisandro Dalcin   }
1805066ea43fSLisandro Dalcin 
1806066ea43fSLisandro Dalcin   /* Create coordinates */
1807066ea43fSLisandro Dalcin   if (highOrder) {
1808066ea43fSLisandro Dalcin 
1809066ea43fSLisandro Dalcin     PetscInt     maxDof = GmshNumNodes_HEX(order)*coordDim;
1810066ea43fSLisandro Dalcin     double       *coords = mesh ? mesh->nodelist->xyz : NULL;
1811066ea43fSLisandro Dalcin     PetscSection section;
1812066ea43fSLisandro Dalcin     PetscScalar  *cellCoords;
1813066ea43fSLisandro Dalcin 
18149566063dSJacob Faibussowitsch     PetscCall(DMSetLocalSection(cdm, NULL));
18159566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(cdm, &coordSection));
18169566063dSJacob Faibussowitsch     PetscCall(PetscSectionClone(coordSection, &section));
18179566063dSJacob Faibussowitsch     PetscCall(DMPlexSetClosurePermutationTensor(cdm, 0, section)); /* XXX Implement DMPlexSetClosurePermutationLexicographic() */
1818066ea43fSLisandro Dalcin 
18199566063dSJacob Faibussowitsch     PetscCall(DMCreateLocalVector(cdm, &coordinates));
18209566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(maxDof, &cellCoords));
1821066ea43fSLisandro Dalcin     for (cell = 0; cell < numCells; ++cell) {
1822066ea43fSLisandro Dalcin       GmshElement *elem = mesh->elements + cell;
1823066ea43fSLisandro Dalcin       const int *lexorder = GmshCellMap[elem->cellType].lexorder();
1824b9bf55e5SMatthew G. Knepley       int s = 0;
1825066ea43fSLisandro Dalcin       for (n = 0; n < elem->numNodes; ++n) {
1826b9bf55e5SMatthew G. Knepley         while (lexorder[n+s] < 0) ++s;
1827b9bf55e5SMatthew G. Knepley         const PetscInt node = elem->nodes[lexorder[n+s]];
1828b9bf55e5SMatthew G. Knepley         for (d = 0; d < coordDim; ++d) cellCoords[(n+s)*coordDim+d] = (PetscReal) coords[node*3+d];
1829b9bf55e5SMatthew G. Knepley       }
1830b9bf55e5SMatthew G. Knepley       if (s) {
1831b9bf55e5SMatthew G. Knepley         /* For the coordinate mapping we weight vertices by -1/4 and edges by 1/2, which we get from Q_2 interpolation */
1832b9bf55e5SMatthew G. Knepley         PetscReal quaCenterWeights[9]  = {-0.25, 0.5, -0.25, 0.5, 0.0, 0.5, -0.25, 0.5, -0.25};
1833b9bf55e5SMatthew G. Knepley         /* For the coordinate mapping we weight vertices by -1/4 and edges by 1/2, which we get from Q_2 interpolation */
1834b9bf55e5SMatthew G. Knepley         PetscReal hexBottomWeights[27] = {-0.25, 0.5,  -0.25, 0.5,  0.0, 0.5,  -0.25, 0.5,  -0.25,
1835b9bf55e5SMatthew G. Knepley                                            0.0,  0.0,   0.0,  0.0,  0.0, 0.0,   0.0,  0.0,   0.0,
1836b9bf55e5SMatthew G. Knepley                                            0.0,  0.0,   0.0,  0.0,  0.0, 0.0,   0.0,  0.0,   0.0};
1837b9bf55e5SMatthew G. Knepley         PetscReal hexFrontWeights[27]  = {-0.25, 0.5,  -0.25, 0.0,  0.0, 0.0,   0.0,  0.0,   0.0,
1838b9bf55e5SMatthew G. Knepley                                            0.5,  0.0,   0.5,  0.0,  0.0, 0.0,   0.0,  0.0,   0.0,
1839b9bf55e5SMatthew G. Knepley                                           -0.25, 0.5,  -0.25, 0.0,  0.0, 0.0,   0.0,  0.0,   0.0};
1840b9bf55e5SMatthew G. Knepley         PetscReal hexLeftWeights[27]   = {-0.25, 0.0,   0.0,  0.5,  0.0, 0.0,  -0.25, 0.0,   0.0,
1841b9bf55e5SMatthew G. Knepley                                            0.5,  0.0,   0.0,  0.0,  0.0, 0.0,   0.5,  0.0,   0.0,
1842b9bf55e5SMatthew G. Knepley                                           -0.25, 0.0,   0.0,  0.5,  0.0, 0.0,  -0.25, 0.0,   0.0};
1843b9bf55e5SMatthew G. Knepley         PetscReal hexRightWeights[27]  = { 0.0,  0.0,  -0.25, 0.0,  0.0, 0.5,   0.0,  0.0,  -0.25,
1844b9bf55e5SMatthew G. Knepley                                            0.0,  0.0,   0.5,  0.0,  0.0, 0.0,   0.0,  0.0,   0.5,
1845b9bf55e5SMatthew G. Knepley                                            0.0,  0.0,  -0.25, 0.0,  0.0, 0.5,   0.0,  0.0,  -0.25};
1846b9bf55e5SMatthew G. Knepley         PetscReal hexBackWeights[27]   = { 0.0,  0.0,   0.0,  0.0,  0.0, 0.0,  -0.25, 0.5,  -0.25,
1847b9bf55e5SMatthew G. Knepley                                            0.0,  0.0,   0.0,  0.0,  0.0, 0.0,   0.5,  0.0,   0.5,
1848b9bf55e5SMatthew G. Knepley                                            0.0,  0.0,   0.0,  0.0,  0.0, 0.0,  -0.25, 0.5,  -0.25};
1849b9bf55e5SMatthew G. Knepley         PetscReal hexTopWeights[27]    = { 0.0,  0.0,   0.0,  0.0,  0.0, 0.0,   0.0,  0.0,   0.0,
1850b9bf55e5SMatthew G. Knepley                                            0.0,  0.0,   0.0,  0.0,  0.0, 0.0,   0.0,  0.0,   0.0,
1851b9bf55e5SMatthew G. Knepley                                           -0.25, 0.5,  -0.25, 0.5,  0.0, 0.5,  -0.25, 0.5,  -0.25};
1852b9bf55e5SMatthew G. Knepley         PetscReal hexCenterWeights[27] = {-0.25, 0.25, -0.25, 0.25, 0.0, 0.25, -0.25, 0.25, -0.25,
1853b9bf55e5SMatthew G. Knepley                                            0.25, 0.0,   0.25, 0.0,  0.0, 0.0,   0.25, 0.0,   0.25,
1854b9bf55e5SMatthew G. Knepley                                           -0.25, 0.25, -0.25, 0.25, 0.0, 0.25, -0.25, 0.25, -0.25};
1855b9bf55e5SMatthew G. Knepley         PetscReal  *sdWeights2[9]      = {NULL, NULL, NULL, NULL, quaCenterWeights, NULL, NULL, NULL, NULL};
1856b9bf55e5SMatthew G. Knepley         PetscReal  *sdWeights3[27]     = {NULL, NULL, NULL, NULL, hexBottomWeights, NULL, NULL, NULL, NULL,
1857b9bf55e5SMatthew G. Knepley                                           NULL, hexFrontWeights, NULL, hexLeftWeights, hexCenterWeights, hexRightWeights, NULL, hexBackWeights, NULL,
1858b9bf55e5SMatthew G. Knepley                                           NULL, NULL, NULL, NULL, hexTopWeights,    NULL, NULL, NULL, NULL};
1859b9bf55e5SMatthew G. Knepley         PetscReal **sdWeights[4]       = {NULL, NULL, sdWeights2, sdWeights3};
1860b9bf55e5SMatthew G. Knepley 
1861b9bf55e5SMatthew G. Knepley         /* Missing entries in serendipity cell, only works for 8-node quad and 20-node hex */
1862b9bf55e5SMatthew G. Knepley         for (n = 0; n < elem->numNodes+s; ++n) {
1863b9bf55e5SMatthew G. Knepley           if (lexorder[n] >= 0) continue;
1864b9bf55e5SMatthew G. Knepley           for (d = 0; d < coordDim; ++d) cellCoords[n*coordDim+d] = 0.0;
1865b9bf55e5SMatthew G. Knepley           for (int bn = 0; bn < elem->numNodes+s; ++bn) {
1866b9bf55e5SMatthew G. Knepley             if (lexorder[bn] < 0) continue;
1867b9bf55e5SMatthew G. Knepley             const PetscReal *weights = sdWeights[coordDim][n];
1868b9bf55e5SMatthew G. Knepley             const PetscInt   bnode   = elem->nodes[lexorder[bn]];
1869b9bf55e5SMatthew G. Knepley             for (d = 0; d < coordDim; ++d) cellCoords[n*coordDim+d] += weights[bn] * (PetscReal) coords[bnode*3+d];
1870b9bf55e5SMatthew G. Knepley           }
1871b9bf55e5SMatthew G. Knepley         }
1872066ea43fSLisandro Dalcin       }
18739566063dSJacob Faibussowitsch       PetscCall(DMPlexVecSetClosure(cdm, section, coordinates, cell, cellCoords, INSERT_VALUES));
1874066ea43fSLisandro Dalcin     }
18759566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&section));
18769566063dSJacob Faibussowitsch     PetscCall(PetscFree(cellCoords));
1877066ea43fSLisandro Dalcin 
1878066ea43fSLisandro Dalcin   } else {
1879066ea43fSLisandro Dalcin 
1880066ea43fSLisandro Dalcin     PetscInt    *nodeMap;
1881066ea43fSLisandro Dalcin     double      *coords = mesh ? mesh->nodelist->xyz : NULL;
1882066ea43fSLisandro Dalcin     PetscScalar *pointCoords;
1883066ea43fSLisandro Dalcin 
18849566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(cdm, &coordSection));
18859566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
18869566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, coordDim));
18870598e1a2SLisandro Dalcin     if (periodic) { /* we need to localize coordinates on cells */
18889566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetChart(coordSection, 0, numCells+numVerts));
1889f45c9589SStefano Zampini     } else {
18909566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetChart(coordSection, numCells, numCells+numVerts));
1891f45c9589SStefano Zampini     }
18920598e1a2SLisandro Dalcin     if (periodic) {
18930598e1a2SLisandro Dalcin       for (cell = 0; cell < numCells; ++cell) {
18940598e1a2SLisandro Dalcin         if (PetscUnlikely(PetscBTLookup(periodicCells, cell))) {
18950598e1a2SLisandro Dalcin           GmshElement *elem = mesh->elements + cell;
18960598e1a2SLisandro Dalcin           PetscInt dof = elem->numVerts * coordDim;
18979566063dSJacob Faibussowitsch           PetscCall(PetscSectionSetDof(coordSection, cell, dof));
18989566063dSJacob Faibussowitsch           PetscCall(PetscSectionSetFieldDof(coordSection, cell, 0, dof));
1899f45c9589SStefano Zampini         }
1900f45c9589SStefano Zampini       }
1901f45c9589SStefano Zampini     }
19020598e1a2SLisandro Dalcin     for (v = numCells; v < numCells+numVerts; ++v) {
19039566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, coordDim));
19049566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, coordDim));
19050598e1a2SLisandro Dalcin     }
19069566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
1907066ea43fSLisandro Dalcin 
19089566063dSJacob Faibussowitsch     PetscCall(DMCreateLocalVector(cdm, &coordinates));
19099566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &pointCoords));
19100598e1a2SLisandro Dalcin     if (periodic) {
19110598e1a2SLisandro Dalcin       for (cell = 0; cell < numCells; ++cell) {
19120598e1a2SLisandro Dalcin         if (PetscUnlikely(PetscBTLookup(periodicCells, cell))) {
19130598e1a2SLisandro Dalcin           GmshElement *elem = mesh->elements + cell;
19140598e1a2SLisandro Dalcin           PetscInt off, node;
19150598e1a2SLisandro Dalcin           for (v = 0; v < elem->numVerts; ++v)
19160598e1a2SLisandro Dalcin             cone[v] = elem->nodes[v];
19179566063dSJacob Faibussowitsch           PetscCall(DMPlexReorderCell(cdm, cell, cone));
19189566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(coordSection, cell, &off));
19190598e1a2SLisandro Dalcin           for (v = 0; v < elem->numVerts; ++v)
19200598e1a2SLisandro Dalcin             for (node = cone[v], d = 0; d < coordDim; ++d)
1921066ea43fSLisandro Dalcin               pointCoords[off++] = (PetscReal) coords[node*3+d];
1922331830f3SMatthew G. Knepley         }
1923331830f3SMatthew G. Knepley       }
1924331830f3SMatthew G. Knepley     }
19259566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(numVerts, &nodeMap));
19260598e1a2SLisandro Dalcin     for (n = 0; n < numNodes; n++)
19270598e1a2SLisandro Dalcin       if (mesh->vertexMap[n] >= 0)
1928066ea43fSLisandro Dalcin         nodeMap[mesh->vertexMap[n]] = n;
19290598e1a2SLisandro Dalcin     for (v = 0; v < numVerts; ++v) {
1930066ea43fSLisandro Dalcin       PetscInt off, node = nodeMap[v];
19319566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, numCells + v, &off));
19320598e1a2SLisandro Dalcin       for (d = 0; d < coordDim; ++d)
1933066ea43fSLisandro Dalcin         pointCoords[off+d] = (PetscReal) coords[node*3+d];
19340598e1a2SLisandro Dalcin     }
19359566063dSJacob Faibussowitsch     PetscCall(PetscFree(nodeMap));
19369566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &pointCoords));
1937066ea43fSLisandro Dalcin 
1938066ea43fSLisandro Dalcin   }
1939066ea43fSLisandro Dalcin 
19409566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) coordinates, "coordinates"));
19419566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, coordDim));
19429566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(*dm, coordinates));
19439566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
19449566063dSJacob Faibussowitsch   PetscCall(DMSetPeriodicity(*dm, periodic, NULL, NULL, NULL));
194511c56cb0SLisandro Dalcin 
19469566063dSJacob Faibussowitsch   PetscCall(GmshMeshDestroy(&mesh));
19479566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&periodicVerts));
19489566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&periodicCells));
194911c56cb0SLisandro Dalcin 
1950066ea43fSLisandro Dalcin   if (highOrder && project)  {
1951066ea43fSLisandro Dalcin     PetscFE         fe;
1952066ea43fSLisandro Dalcin     const char      prefix[]   = "dm_plex_gmsh_project_";
1953066ea43fSLisandro Dalcin     PetscBool       continuity = periodic ? PETSC_FALSE : PETSC_TRUE;
1954066ea43fSLisandro Dalcin     PetscDTNodeType nodeType   = PETSCDTNODES_GAUSSJACOBI;
1955066ea43fSLisandro Dalcin 
1956066ea43fSLisandro Dalcin     if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */
1957066ea43fSLisandro Dalcin 
19589566063dSJacob Faibussowitsch     PetscCall(GmshCreateFE(comm, prefix, isSimplex, continuity, nodeType, dim, coordDim, order, &fe));
19599566063dSJacob Faibussowitsch     PetscCall(PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_project_fe_view"));
19609566063dSJacob Faibussowitsch     PetscCall(DMProjectCoordinates(*dm, fe));
19619566063dSJacob Faibussowitsch     PetscCall(PetscFEDestroy(&fe));
1962066ea43fSLisandro Dalcin   }
1963066ea43fSLisandro Dalcin 
19649566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CreateGmsh,*dm,NULL,NULL,NULL));
1965331830f3SMatthew G. Knepley   PetscFunctionReturn(0);
1966331830f3SMatthew G. Knepley }
1967