xref: /petsc/src/dm/impls/plex/plexgmsh.c (revision dd4005766979d6c32c7873f45a6074c17defa719)
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 
16066ea43fSLisandro Dalcin #define GMSH_LEXORDER_LIST(T) \
17066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T,  1)     \
18066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T,  2)     \
19066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T,  3)     \
20066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T,  4)     \
21066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T,  5)     \
22066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T,  6)     \
23066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T,  7)     \
24066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T,  8)     \
25066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T,  9)     \
26066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 10)
27066ea43fSLisandro Dalcin 
28066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(VTX, 0)
29066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(SEG)
30066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(TRI)
31066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(QUA)
32066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(TET)
33066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(HEX)
34066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(PRI)
35066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(PYR)
36066ea43fSLisandro Dalcin 
37066ea43fSLisandro Dalcin typedef enum {
38066ea43fSLisandro Dalcin   GMSH_VTX = 0,
39066ea43fSLisandro Dalcin   GMSH_SEG = 1,
40066ea43fSLisandro Dalcin   GMSH_TRI = 2,
41066ea43fSLisandro Dalcin   GMSH_QUA = 3,
42066ea43fSLisandro Dalcin   GMSH_TET = 4,
43066ea43fSLisandro Dalcin   GMSH_HEX = 5,
44066ea43fSLisandro Dalcin   GMSH_PRI = 6,
45066ea43fSLisandro Dalcin   GMSH_PYR = 7,
46066ea43fSLisandro Dalcin   GMSH_NUM_POLYTOPES = 8
47066ea43fSLisandro Dalcin } GmshPolytopeType;
48066ea43fSLisandro Dalcin 
49de78e4feSLisandro Dalcin typedef struct {
500598e1a2SLisandro Dalcin   int   cellType;
51066ea43fSLisandro Dalcin   int   polytope;
520598e1a2SLisandro Dalcin   int   dim;
530598e1a2SLisandro Dalcin   int   order;
54066ea43fSLisandro Dalcin   int   numVerts;
550598e1a2SLisandro Dalcin   int   numNodes;
56066ea43fSLisandro Dalcin   int* (*lexorder)(void);
570598e1a2SLisandro Dalcin } GmshCellInfo;
580598e1a2SLisandro Dalcin 
59066ea43fSLisandro Dalcin #define GmshCellEntry(cellType, polytope, dim, order) \
60066ea43fSLisandro Dalcin   {cellType, GMSH_##polytope, dim, order, \
61066ea43fSLisandro Dalcin    GmshNumNodes_##polytope(1), \
62066ea43fSLisandro Dalcin    GmshNumNodes_##polytope(order), \
63066ea43fSLisandro Dalcin    GmshLexOrder_##polytope##_##order}
640598e1a2SLisandro Dalcin 
650598e1a2SLisandro Dalcin static const GmshCellInfo GmshCellTable[] = {
66066ea43fSLisandro Dalcin   GmshCellEntry( 15, VTX, 0,  0),
670598e1a2SLisandro Dalcin 
68066ea43fSLisandro Dalcin   GmshCellEntry(  1, SEG, 1,  1),
69066ea43fSLisandro Dalcin   GmshCellEntry(  8, SEG, 1,  2),
70066ea43fSLisandro Dalcin   GmshCellEntry( 26, SEG, 1,  3),
71066ea43fSLisandro Dalcin   GmshCellEntry( 27, SEG, 1,  4),
72066ea43fSLisandro Dalcin   GmshCellEntry( 28, SEG, 1,  5),
73066ea43fSLisandro Dalcin   GmshCellEntry( 62, SEG, 1,  6),
74066ea43fSLisandro Dalcin   GmshCellEntry( 63, SEG, 1,  7),
75066ea43fSLisandro Dalcin   GmshCellEntry( 64, SEG, 1,  8),
76066ea43fSLisandro Dalcin   GmshCellEntry( 65, SEG, 1,  9),
77066ea43fSLisandro Dalcin   GmshCellEntry( 66, SEG, 1, 10),
780598e1a2SLisandro Dalcin 
79066ea43fSLisandro Dalcin   GmshCellEntry(  2, TRI, 2,  1),
80066ea43fSLisandro Dalcin   GmshCellEntry(  9, TRI, 2,  2),
81066ea43fSLisandro Dalcin   GmshCellEntry( 21, TRI, 2,  3),
82066ea43fSLisandro Dalcin   GmshCellEntry( 23, TRI, 2,  4),
83066ea43fSLisandro Dalcin   GmshCellEntry( 25, TRI, 2,  5),
84066ea43fSLisandro Dalcin   GmshCellEntry( 42, TRI, 2,  6),
85066ea43fSLisandro Dalcin   GmshCellEntry( 43, TRI, 2,  7),
86066ea43fSLisandro Dalcin   GmshCellEntry( 44, TRI, 2,  8),
87066ea43fSLisandro Dalcin   GmshCellEntry( 45, TRI, 2,  9),
88066ea43fSLisandro Dalcin   GmshCellEntry( 46, TRI, 2, 10),
890598e1a2SLisandro Dalcin 
90066ea43fSLisandro Dalcin   GmshCellEntry(  3, QUA, 2,  1),
91066ea43fSLisandro Dalcin   GmshCellEntry( 10, QUA, 2,  2),
92066ea43fSLisandro Dalcin   GmshCellEntry( 36, QUA, 2,  3),
93066ea43fSLisandro Dalcin   GmshCellEntry( 37, QUA, 2,  4),
94066ea43fSLisandro Dalcin   GmshCellEntry( 38, QUA, 2,  5),
95066ea43fSLisandro Dalcin   GmshCellEntry( 47, QUA, 2,  6),
96066ea43fSLisandro Dalcin   GmshCellEntry( 48, QUA, 2,  7),
97066ea43fSLisandro Dalcin   GmshCellEntry( 49, QUA, 2,  8),
98066ea43fSLisandro Dalcin   GmshCellEntry( 50, QUA, 2,  9),
99066ea43fSLisandro Dalcin   GmshCellEntry( 51, QUA, 2, 10),
1000598e1a2SLisandro Dalcin 
101066ea43fSLisandro Dalcin   GmshCellEntry(  4, TET, 3,  1),
102066ea43fSLisandro Dalcin   GmshCellEntry( 11, TET, 3,  2),
103066ea43fSLisandro Dalcin   GmshCellEntry( 29, TET, 3,  3),
104066ea43fSLisandro Dalcin   GmshCellEntry( 30, TET, 3,  4),
105066ea43fSLisandro Dalcin   GmshCellEntry( 31, TET, 3,  5),
106066ea43fSLisandro Dalcin   GmshCellEntry( 71, TET, 3,  6),
107066ea43fSLisandro Dalcin   GmshCellEntry( 72, TET, 3,  7),
108066ea43fSLisandro Dalcin   GmshCellEntry( 73, TET, 3,  8),
109066ea43fSLisandro Dalcin   GmshCellEntry( 74, TET, 3,  9),
110066ea43fSLisandro Dalcin   GmshCellEntry( 75, TET, 3, 10),
1110598e1a2SLisandro Dalcin 
112066ea43fSLisandro Dalcin   GmshCellEntry(  5, HEX, 3,  1),
113066ea43fSLisandro Dalcin   GmshCellEntry( 12, HEX, 3,  2),
114066ea43fSLisandro Dalcin   GmshCellEntry( 92, HEX, 3,  3),
115066ea43fSLisandro Dalcin   GmshCellEntry( 93, HEX, 3,  4),
116066ea43fSLisandro Dalcin   GmshCellEntry( 94, HEX, 3,  5),
117066ea43fSLisandro Dalcin   GmshCellEntry( 95, HEX, 3,  6),
118066ea43fSLisandro Dalcin   GmshCellEntry( 96, HEX, 3,  7),
119066ea43fSLisandro Dalcin   GmshCellEntry( 97, HEX, 3,  8),
120066ea43fSLisandro Dalcin   GmshCellEntry( 98, HEX, 3,  9),
121066ea43fSLisandro Dalcin   GmshCellEntry( -1, HEX, 3, 10),
1220598e1a2SLisandro Dalcin 
123066ea43fSLisandro Dalcin   GmshCellEntry(  6, PRI, 3,  1),
124066ea43fSLisandro Dalcin   GmshCellEntry( 13, PRI, 3,  2),
125066ea43fSLisandro Dalcin   GmshCellEntry( 90, PRI, 3,  3),
126066ea43fSLisandro Dalcin   GmshCellEntry( 91, PRI, 3,  4),
127066ea43fSLisandro Dalcin   GmshCellEntry(106, PRI, 3,  5),
128066ea43fSLisandro Dalcin   GmshCellEntry(107, PRI, 3,  6),
129066ea43fSLisandro Dalcin   GmshCellEntry(108, PRI, 3,  7),
130066ea43fSLisandro Dalcin   GmshCellEntry(109, PRI, 3,  8),
131066ea43fSLisandro Dalcin   GmshCellEntry(110, PRI, 3,  9),
132066ea43fSLisandro Dalcin   GmshCellEntry( -1, PRI, 3, 10),
1330598e1a2SLisandro Dalcin 
134066ea43fSLisandro Dalcin   GmshCellEntry(  7, PYR, 3,  1),
135066ea43fSLisandro Dalcin   GmshCellEntry( 14, PYR, 3,  2),
136066ea43fSLisandro Dalcin   GmshCellEntry(118, PYR, 3,  3),
137066ea43fSLisandro Dalcin   GmshCellEntry(119, PYR, 3,  4),
138066ea43fSLisandro Dalcin   GmshCellEntry(120, PYR, 3,  5),
139066ea43fSLisandro Dalcin   GmshCellEntry(121, PYR, 3,  6),
140066ea43fSLisandro Dalcin   GmshCellEntry(122, PYR, 3,  7),
141066ea43fSLisandro Dalcin   GmshCellEntry(123, PYR, 3,  8),
142066ea43fSLisandro Dalcin   GmshCellEntry(124, PYR, 3,  9),
143066ea43fSLisandro Dalcin   GmshCellEntry( -1, PYR, 3, 10)
1440598e1a2SLisandro Dalcin 
1450598e1a2SLisandro Dalcin #if 0
146066ea43fSLisandro Dalcin   {20, GMSH_TRI, 2, 3, 3,  9, NULL},
147066ea43fSLisandro Dalcin   {16, GMSH_QUA, 2, 2, 4,  8, NULL},
148066ea43fSLisandro Dalcin   {17, GMSH_HEX, 3, 2, 8, 20, NULL},
149066ea43fSLisandro Dalcin   {18, GMSH_PRI, 3, 2, 6, 15, NULL},
150066ea43fSLisandro Dalcin   {19, GMSH_PYR, 3, 2, 5, 13, NULL},
1510598e1a2SLisandro Dalcin #endif
1520598e1a2SLisandro Dalcin };
1530598e1a2SLisandro Dalcin 
1540598e1a2SLisandro Dalcin static GmshCellInfo GmshCellMap[150];
1550598e1a2SLisandro Dalcin 
1560598e1a2SLisandro Dalcin static PetscErrorCode GmshCellInfoSetUp(void)
1570598e1a2SLisandro Dalcin {
1580598e1a2SLisandro Dalcin   size_t           i, n;
1590598e1a2SLisandro Dalcin   static PetscBool called = PETSC_FALSE;
1600598e1a2SLisandro Dalcin 
1610598e1a2SLisandro Dalcin   if (called) return 0;
1620598e1a2SLisandro Dalcin   PetscFunctionBegin;
1630598e1a2SLisandro Dalcin   called = PETSC_TRUE;
1640598e1a2SLisandro Dalcin   n = sizeof(GmshCellMap)/sizeof(GmshCellMap[0]);
1650598e1a2SLisandro Dalcin   for (i = 0; i < n; ++i) {
1660598e1a2SLisandro Dalcin     GmshCellMap[i].cellType = -1;
167066ea43fSLisandro Dalcin     GmshCellMap[i].polytope = -1;
1680598e1a2SLisandro Dalcin   }
1690598e1a2SLisandro Dalcin   n = sizeof(GmshCellTable)/sizeof(GmshCellTable[0]);
170066ea43fSLisandro Dalcin   for (i = 0; i < n; ++i) {
171066ea43fSLisandro Dalcin     if (GmshCellTable[i].cellType <= 0) continue;
172066ea43fSLisandro Dalcin     GmshCellMap[GmshCellTable[i].cellType] = GmshCellTable[i];
173066ea43fSLisandro Dalcin   }
1740598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
1750598e1a2SLisandro Dalcin }
1760598e1a2SLisandro Dalcin 
1770598e1a2SLisandro Dalcin #define GmshCellTypeCheck(ct) 0; do { \
1780598e1a2SLisandro Dalcin     const int _ct_ = (int)ct; \
1790598e1a2SLisandro Dalcin     if (_ct_ < 0 || _ct_ >= (int)(sizeof(GmshCellMap)/sizeof(GmshCellMap[0]))) \
1800598e1a2SLisandro Dalcin       SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid Gmsh element type %d", _ct_); \
1810598e1a2SLisandro Dalcin     if (GmshCellMap[_ct_].cellType != _ct_) \
1820598e1a2SLisandro Dalcin       SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported Gmsh element type %d", _ct_); \
183066ea43fSLisandro Dalcin     if (GmshCellMap[_ct_].polytope == -1) \
1840598e1a2SLisandro Dalcin       SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported Gmsh element type %d", _ct_); \
1850598e1a2SLisandro Dalcin   } while (0)
1860598e1a2SLisandro Dalcin 
1870598e1a2SLisandro Dalcin typedef struct {
188698a79b9SLisandro Dalcin   PetscViewer  viewer;
189698a79b9SLisandro Dalcin   int          fileFormat;
190698a79b9SLisandro Dalcin   int          dataSize;
191698a79b9SLisandro Dalcin   PetscBool    binary;
192698a79b9SLisandro Dalcin   PetscBool    byteSwap;
193698a79b9SLisandro Dalcin   size_t       wlen;
194698a79b9SLisandro Dalcin   void        *wbuf;
195698a79b9SLisandro Dalcin   size_t       slen;
196698a79b9SLisandro Dalcin   void        *sbuf;
1970598e1a2SLisandro Dalcin   PetscInt    *nbuf;
1980598e1a2SLisandro Dalcin   PetscInt     nodeStart;
1990598e1a2SLisandro Dalcin   PetscInt     nodeEnd;
20033a088b6SMatthew G. Knepley   PetscInt    *nodeMap;
201698a79b9SLisandro Dalcin } GmshFile;
202de78e4feSLisandro Dalcin 
203698a79b9SLisandro Dalcin static PetscErrorCode GmshBufferGet(GmshFile *gmsh, size_t count, size_t eltsize, void *buf)
204de78e4feSLisandro Dalcin {
205de78e4feSLisandro Dalcin   size_t         size = count * eltsize;
20611c56cb0SLisandro Dalcin   PetscErrorCode ierr;
20711c56cb0SLisandro Dalcin 
20811c56cb0SLisandro Dalcin   PetscFunctionBegin;
209698a79b9SLisandro Dalcin   if (gmsh->wlen < size) {
210698a79b9SLisandro Dalcin     ierr = PetscFree(gmsh->wbuf);CHKERRQ(ierr);
211698a79b9SLisandro Dalcin     ierr = PetscMalloc(size, &gmsh->wbuf);CHKERRQ(ierr);
212698a79b9SLisandro Dalcin     gmsh->wlen = size;
213de78e4feSLisandro Dalcin   }
214698a79b9SLisandro Dalcin   *(void**)buf = size ? gmsh->wbuf : NULL;
215de78e4feSLisandro Dalcin   PetscFunctionReturn(0);
216de78e4feSLisandro Dalcin }
217de78e4feSLisandro Dalcin 
218698a79b9SLisandro Dalcin static PetscErrorCode GmshBufferSizeGet(GmshFile *gmsh, size_t count, void *buf)
219698a79b9SLisandro Dalcin {
220698a79b9SLisandro Dalcin   size_t         dataSize = (size_t)gmsh->dataSize;
221698a79b9SLisandro Dalcin   size_t         size = count * dataSize;
222698a79b9SLisandro Dalcin   PetscErrorCode ierr;
223698a79b9SLisandro Dalcin 
224698a79b9SLisandro Dalcin   PetscFunctionBegin;
225698a79b9SLisandro Dalcin   if (gmsh->slen < size) {
226698a79b9SLisandro Dalcin     ierr = PetscFree(gmsh->sbuf);CHKERRQ(ierr);
227698a79b9SLisandro Dalcin     ierr = PetscMalloc(size, &gmsh->sbuf);CHKERRQ(ierr);
228698a79b9SLisandro Dalcin     gmsh->slen = size;
229698a79b9SLisandro Dalcin   }
230698a79b9SLisandro Dalcin   *(void**)buf = size ? gmsh->sbuf : NULL;
231698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
232698a79b9SLisandro Dalcin }
233698a79b9SLisandro Dalcin 
234698a79b9SLisandro Dalcin static PetscErrorCode GmshRead(GmshFile *gmsh, void *buf, PetscInt count, PetscDataType dtype)
235de78e4feSLisandro Dalcin {
236de78e4feSLisandro Dalcin   PetscErrorCode ierr;
237de78e4feSLisandro Dalcin   PetscFunctionBegin;
238698a79b9SLisandro Dalcin   ierr = PetscViewerRead(gmsh->viewer, buf, count, NULL, dtype);CHKERRQ(ierr);
239698a79b9SLisandro Dalcin   if (gmsh->byteSwap) {ierr = PetscByteSwap(buf, dtype, count);CHKERRQ(ierr);}
240698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
241698a79b9SLisandro Dalcin }
242698a79b9SLisandro Dalcin 
243698a79b9SLisandro Dalcin static PetscErrorCode GmshReadString(GmshFile *gmsh, char *buf, PetscInt count)
244698a79b9SLisandro Dalcin {
245698a79b9SLisandro Dalcin   PetscErrorCode ierr;
246698a79b9SLisandro Dalcin   PetscFunctionBegin;
247698a79b9SLisandro Dalcin   ierr = PetscViewerRead(gmsh->viewer, buf, count, NULL, PETSC_STRING);CHKERRQ(ierr);
248698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
249698a79b9SLisandro Dalcin }
250698a79b9SLisandro Dalcin 
251d6689ca9SLisandro Dalcin static PetscErrorCode GmshMatch(PETSC_UNUSED GmshFile *gmsh, const char Section[], char line[PETSC_MAX_PATH_LEN], PetscBool *match)
252d6689ca9SLisandro Dalcin {
253d6689ca9SLisandro Dalcin   PetscErrorCode ierr;
254d6689ca9SLisandro Dalcin   PetscFunctionBegin;
255d6689ca9SLisandro Dalcin   ierr = PetscStrcmp(line, Section, match);CHKERRQ(ierr);
256d6689ca9SLisandro Dalcin   PetscFunctionReturn(0);
257d6689ca9SLisandro Dalcin }
258d6689ca9SLisandro Dalcin 
259d6689ca9SLisandro Dalcin static PetscErrorCode GmshExpect(GmshFile *gmsh, const char Section[], char line[PETSC_MAX_PATH_LEN])
260d6689ca9SLisandro Dalcin {
261d6689ca9SLisandro Dalcin   PetscBool      match;
262d6689ca9SLisandro Dalcin   PetscErrorCode ierr;
263d6689ca9SLisandro Dalcin 
264d6689ca9SLisandro Dalcin   PetscFunctionBegin;
265d6689ca9SLisandro Dalcin   ierr = GmshMatch(gmsh, Section, line, &match);CHKERRQ(ierr);
2660598e1a2SLisandro Dalcin   if (!match) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file, expecting %s",Section);
267d6689ca9SLisandro Dalcin   PetscFunctionReturn(0);
268d6689ca9SLisandro Dalcin }
269d6689ca9SLisandro Dalcin 
270d6689ca9SLisandro Dalcin static PetscErrorCode GmshReadSection(GmshFile *gmsh, char line[PETSC_MAX_PATH_LEN])
271d6689ca9SLisandro Dalcin {
272d6689ca9SLisandro Dalcin   PetscBool      match;
273d6689ca9SLisandro Dalcin   PetscErrorCode ierr;
274d6689ca9SLisandro Dalcin 
275d6689ca9SLisandro Dalcin   PetscFunctionBegin;
276d6689ca9SLisandro Dalcin   while (PETSC_TRUE) {
277d6689ca9SLisandro Dalcin     ierr = GmshReadString(gmsh, line, 1);CHKERRQ(ierr);
278d6689ca9SLisandro Dalcin     ierr = GmshMatch(gmsh, "$Comments", line, &match);CHKERRQ(ierr);
279d6689ca9SLisandro Dalcin     if (!match) break;
280d6689ca9SLisandro Dalcin     while (PETSC_TRUE) {
281d6689ca9SLisandro Dalcin       ierr = GmshReadString(gmsh, line, 1);CHKERRQ(ierr);
282d6689ca9SLisandro Dalcin       ierr = GmshMatch(gmsh, "$EndComments", line, &match);CHKERRQ(ierr);
283d6689ca9SLisandro Dalcin       if (match) break;
284d6689ca9SLisandro Dalcin     }
285d6689ca9SLisandro Dalcin   }
286d6689ca9SLisandro Dalcin   PetscFunctionReturn(0);
287d6689ca9SLisandro Dalcin }
288d6689ca9SLisandro Dalcin 
289d6689ca9SLisandro Dalcin static PetscErrorCode GmshReadEndSection(GmshFile *gmsh, const char EndSection[], char line[PETSC_MAX_PATH_LEN])
290d6689ca9SLisandro Dalcin {
291d6689ca9SLisandro Dalcin   PetscErrorCode ierr;
292d6689ca9SLisandro Dalcin   PetscFunctionBegin;
293d6689ca9SLisandro Dalcin   ierr = GmshReadString(gmsh, line, 1);CHKERRQ(ierr);
294d6689ca9SLisandro Dalcin   ierr = GmshExpect(gmsh, EndSection, line);CHKERRQ(ierr);
295d6689ca9SLisandro Dalcin   PetscFunctionReturn(0);
296d6689ca9SLisandro Dalcin }
297d6689ca9SLisandro Dalcin 
298698a79b9SLisandro Dalcin static PetscErrorCode GmshReadSize(GmshFile *gmsh, PetscInt *buf, PetscInt count)
299698a79b9SLisandro Dalcin {
300698a79b9SLisandro Dalcin   PetscInt       i;
301698a79b9SLisandro Dalcin   size_t         dataSize = (size_t)gmsh->dataSize;
302698a79b9SLisandro Dalcin   PetscErrorCode ierr;
303698a79b9SLisandro Dalcin 
304698a79b9SLisandro Dalcin   PetscFunctionBegin;
305698a79b9SLisandro Dalcin   if (dataSize == sizeof(PetscInt)) {
306698a79b9SLisandro Dalcin     ierr = GmshRead(gmsh, buf, count, PETSC_INT);CHKERRQ(ierr);
307698a79b9SLisandro Dalcin   } else  if (dataSize == sizeof(int)) {
308698a79b9SLisandro Dalcin     int *ibuf = NULL;
30989d5b078SSatish Balay     ierr = GmshBufferSizeGet(gmsh, count, &ibuf);CHKERRQ(ierr);
310698a79b9SLisandro Dalcin     ierr = GmshRead(gmsh, ibuf, count, PETSC_ENUM);CHKERRQ(ierr);
311698a79b9SLisandro Dalcin     for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i];
312698a79b9SLisandro Dalcin   } else  if (dataSize == sizeof(long)) {
313698a79b9SLisandro Dalcin     long *ibuf = NULL;
31489d5b078SSatish Balay     ierr = GmshBufferSizeGet(gmsh, count, &ibuf);CHKERRQ(ierr);
315698a79b9SLisandro Dalcin     ierr = GmshRead(gmsh, ibuf, count, PETSC_LONG);CHKERRQ(ierr);
316698a79b9SLisandro Dalcin     for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i];
317698a79b9SLisandro Dalcin   } else if (dataSize == sizeof(PetscInt64)) {
318698a79b9SLisandro Dalcin     PetscInt64 *ibuf = NULL;
31989d5b078SSatish Balay     ierr = GmshBufferSizeGet(gmsh, count, &ibuf);CHKERRQ(ierr);
320698a79b9SLisandro Dalcin     ierr = GmshRead(gmsh, ibuf, count, PETSC_INT64);CHKERRQ(ierr);
321698a79b9SLisandro Dalcin     for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i];
322698a79b9SLisandro Dalcin   }
323698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
324698a79b9SLisandro Dalcin }
325698a79b9SLisandro Dalcin 
326698a79b9SLisandro Dalcin static PetscErrorCode GmshReadInt(GmshFile *gmsh, int *buf, PetscInt count)
327698a79b9SLisandro Dalcin {
328698a79b9SLisandro Dalcin   PetscErrorCode ierr;
329698a79b9SLisandro Dalcin   PetscFunctionBegin;
330698a79b9SLisandro Dalcin   ierr = GmshRead(gmsh, buf, count, PETSC_ENUM);CHKERRQ(ierr);
331698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
332698a79b9SLisandro Dalcin }
333698a79b9SLisandro Dalcin 
334698a79b9SLisandro Dalcin static PetscErrorCode GmshReadDouble(GmshFile *gmsh, double *buf, PetscInt count)
335698a79b9SLisandro Dalcin {
336698a79b9SLisandro Dalcin   PetscErrorCode ierr;
337698a79b9SLisandro Dalcin   PetscFunctionBegin;
338698a79b9SLisandro Dalcin   ierr = GmshRead(gmsh, buf, count, PETSC_DOUBLE);CHKERRQ(ierr);
339de78e4feSLisandro Dalcin   PetscFunctionReturn(0);
340de78e4feSLisandro Dalcin }
341de78e4feSLisandro Dalcin 
342de78e4feSLisandro Dalcin typedef struct {
3430598e1a2SLisandro Dalcin   PetscInt id;       /* Entity ID */
3440598e1a2SLisandro Dalcin   PetscInt dim;      /* Dimension */
345de78e4feSLisandro Dalcin   double   bbox[6];  /* Bounding box */
346de78e4feSLisandro Dalcin   PetscInt numTags;  /* Size of tag array */
347de78e4feSLisandro Dalcin   int      tags[4];  /* Tag array */
348de78e4feSLisandro Dalcin } GmshEntity;
349de78e4feSLisandro Dalcin 
350de78e4feSLisandro Dalcin typedef struct {
351730356f6SLisandro Dalcin   GmshEntity *entity[4];
352730356f6SLisandro Dalcin   PetscHMapI  entityMap[4];
353730356f6SLisandro Dalcin } GmshEntities;
354730356f6SLisandro Dalcin 
355698a79b9SLisandro Dalcin static PetscErrorCode GmshEntitiesCreate(PetscInt count[4], GmshEntities **entities)
356730356f6SLisandro Dalcin {
357730356f6SLisandro Dalcin   PetscInt       dim;
358730356f6SLisandro Dalcin   PetscErrorCode ierr;
359730356f6SLisandro Dalcin 
360730356f6SLisandro Dalcin   PetscFunctionBegin;
361730356f6SLisandro Dalcin   ierr = PetscNew(entities);CHKERRQ(ierr);
362730356f6SLisandro Dalcin   for (dim = 0; dim < 4; ++dim) {
363730356f6SLisandro Dalcin     ierr = PetscCalloc1(count[dim], &(*entities)->entity[dim]);CHKERRQ(ierr);
364730356f6SLisandro Dalcin     ierr = PetscHMapICreate(&(*entities)->entityMap[dim]);CHKERRQ(ierr);
365730356f6SLisandro Dalcin   }
366730356f6SLisandro Dalcin   PetscFunctionReturn(0);
367730356f6SLisandro Dalcin }
368730356f6SLisandro Dalcin 
3690598e1a2SLisandro Dalcin static PetscErrorCode GmshEntitiesDestroy(GmshEntities **entities)
3700598e1a2SLisandro Dalcin {
3710598e1a2SLisandro Dalcin   PetscInt       dim;
3720598e1a2SLisandro Dalcin   PetscErrorCode ierr;
3730598e1a2SLisandro Dalcin 
3740598e1a2SLisandro Dalcin   PetscFunctionBegin;
3750598e1a2SLisandro Dalcin   if (!*entities) PetscFunctionReturn(0);
3760598e1a2SLisandro Dalcin   for (dim = 0; dim < 4; ++dim) {
3770598e1a2SLisandro Dalcin     ierr = PetscFree((*entities)->entity[dim]);CHKERRQ(ierr);
3780598e1a2SLisandro Dalcin     ierr = PetscHMapIDestroy(&(*entities)->entityMap[dim]);CHKERRQ(ierr);
3790598e1a2SLisandro Dalcin   }
3800598e1a2SLisandro Dalcin   ierr = PetscFree((*entities));CHKERRQ(ierr);
3810598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
3820598e1a2SLisandro Dalcin }
3830598e1a2SLisandro Dalcin 
384730356f6SLisandro Dalcin static PetscErrorCode GmshEntitiesAdd(GmshEntities *entities, PetscInt index, PetscInt dim, PetscInt eid, GmshEntity** entity)
385730356f6SLisandro Dalcin {
386730356f6SLisandro Dalcin   PetscErrorCode ierr;
3870598e1a2SLisandro Dalcin 
388730356f6SLisandro Dalcin   PetscFunctionBegin;
389730356f6SLisandro Dalcin   ierr = PetscHMapISet(entities->entityMap[dim], eid, index);CHKERRQ(ierr);
390730356f6SLisandro Dalcin   entities->entity[dim][index].dim = dim;
391730356f6SLisandro Dalcin   entities->entity[dim][index].id  = eid;
392730356f6SLisandro Dalcin   if (entity) *entity = &entities->entity[dim][index];
393730356f6SLisandro Dalcin   PetscFunctionReturn(0);
394730356f6SLisandro Dalcin }
395730356f6SLisandro Dalcin 
396730356f6SLisandro Dalcin static PetscErrorCode GmshEntitiesGet(GmshEntities *entities, PetscInt dim, PetscInt eid, GmshEntity** entity)
397730356f6SLisandro Dalcin {
398730356f6SLisandro Dalcin   PetscInt       index;
399730356f6SLisandro Dalcin   PetscErrorCode ierr;
400730356f6SLisandro Dalcin 
401730356f6SLisandro Dalcin   PetscFunctionBegin;
402730356f6SLisandro Dalcin   ierr = PetscHMapIGet(entities->entityMap[dim], eid, &index);CHKERRQ(ierr);
403730356f6SLisandro Dalcin   *entity = &entities->entity[dim][index];
404730356f6SLisandro Dalcin   PetscFunctionReturn(0);
405730356f6SLisandro Dalcin }
406730356f6SLisandro Dalcin 
4070598e1a2SLisandro Dalcin typedef struct {
4080598e1a2SLisandro Dalcin   PetscInt *id;   /* Node IDs */
4090598e1a2SLisandro Dalcin   double   *xyz;  /* Coordinates */
4100598e1a2SLisandro Dalcin } GmshNodes;
4110598e1a2SLisandro Dalcin 
4120598e1a2SLisandro Dalcin static PetscErrorCode GmshNodesCreate(PetscInt count, GmshNodes **nodes)
413730356f6SLisandro Dalcin {
414730356f6SLisandro Dalcin   PetscErrorCode ierr;
415730356f6SLisandro Dalcin 
416730356f6SLisandro Dalcin   PetscFunctionBegin;
4170598e1a2SLisandro Dalcin   ierr = PetscNew(nodes);CHKERRQ(ierr);
4180598e1a2SLisandro Dalcin   ierr = PetscMalloc1(count*1, &(*nodes)->id);CHKERRQ(ierr);
4190598e1a2SLisandro Dalcin   ierr = PetscMalloc1(count*3, &(*nodes)->xyz);CHKERRQ(ierr);
4200598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
421730356f6SLisandro Dalcin }
4220598e1a2SLisandro Dalcin 
4230598e1a2SLisandro Dalcin static PetscErrorCode GmshNodesDestroy(GmshNodes **nodes)
4240598e1a2SLisandro Dalcin {
4250598e1a2SLisandro Dalcin   PetscErrorCode ierr;
4260598e1a2SLisandro Dalcin   PetscFunctionBegin;
4270598e1a2SLisandro Dalcin   if (!*nodes) PetscFunctionReturn(0);
4280598e1a2SLisandro Dalcin   ierr = PetscFree((*nodes)->id);CHKERRQ(ierr);
4290598e1a2SLisandro Dalcin   ierr = PetscFree((*nodes)->xyz);CHKERRQ(ierr);
4300598e1a2SLisandro Dalcin   ierr = PetscFree((*nodes));CHKERRQ(ierr);
431730356f6SLisandro Dalcin   PetscFunctionReturn(0);
432730356f6SLisandro Dalcin }
433730356f6SLisandro Dalcin 
434730356f6SLisandro Dalcin typedef struct {
4350598e1a2SLisandro Dalcin   PetscInt id;       /* Element ID */
4360598e1a2SLisandro Dalcin   PetscInt dim;      /* Dimension */
437de78e4feSLisandro Dalcin   PetscInt cellType; /* Cell type */
4380598e1a2SLisandro Dalcin   PetscInt numVerts; /* Size of vertex array */
439de78e4feSLisandro Dalcin   PetscInt numNodes; /* Size of node array */
4400598e1a2SLisandro Dalcin   PetscInt *nodes;   /* Vertex/Node array */
441de78e4feSLisandro Dalcin   PetscInt numTags;  /* Size of tag array */
442de78e4feSLisandro Dalcin   int      tags[4];  /* Tag array */
443de78e4feSLisandro Dalcin } GmshElement;
444de78e4feSLisandro Dalcin 
4450598e1a2SLisandro Dalcin static PetscErrorCode GmshElementsCreate(PetscInt count, GmshElement **elements)
4460598e1a2SLisandro Dalcin {
4470598e1a2SLisandro Dalcin   PetscErrorCode ierr;
4480598e1a2SLisandro Dalcin 
4490598e1a2SLisandro Dalcin   PetscFunctionBegin;
4500598e1a2SLisandro Dalcin   ierr = PetscCalloc1(count, elements);CHKERRQ(ierr);
4510598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
4520598e1a2SLisandro Dalcin }
4530598e1a2SLisandro Dalcin 
4540598e1a2SLisandro Dalcin static PetscErrorCode GmshElementsDestroy(GmshElement **elements)
4550598e1a2SLisandro Dalcin {
4560598e1a2SLisandro Dalcin   PetscErrorCode ierr;
4570598e1a2SLisandro Dalcin 
4580598e1a2SLisandro Dalcin   PetscFunctionBegin;
4590598e1a2SLisandro Dalcin   if (!*elements) PetscFunctionReturn(0);
4600598e1a2SLisandro Dalcin   ierr = PetscFree(*elements);CHKERRQ(ierr);
4610598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
4620598e1a2SLisandro Dalcin }
4630598e1a2SLisandro Dalcin 
4640598e1a2SLisandro Dalcin typedef struct {
4650598e1a2SLisandro Dalcin   PetscInt       dim;
466066ea43fSLisandro Dalcin   PetscInt       order;
4670598e1a2SLisandro Dalcin   GmshEntities  *entities;
4680598e1a2SLisandro Dalcin   PetscInt       numNodes;
4690598e1a2SLisandro Dalcin   GmshNodes     *nodelist;
4700598e1a2SLisandro Dalcin   PetscInt       numElems;
4710598e1a2SLisandro Dalcin   GmshElement   *elements;
4720598e1a2SLisandro Dalcin   PetscInt       numVerts;
4730598e1a2SLisandro Dalcin   PetscInt       numCells;
4740598e1a2SLisandro Dalcin   PetscInt      *periodMap;
4750598e1a2SLisandro Dalcin   PetscInt      *vertexMap;
4760598e1a2SLisandro Dalcin   PetscSegBuffer segbuf;
4770598e1a2SLisandro Dalcin } GmshMesh;
4780598e1a2SLisandro Dalcin 
4790598e1a2SLisandro Dalcin static PetscErrorCode GmshMeshCreate(GmshMesh **mesh)
4800598e1a2SLisandro Dalcin {
4810598e1a2SLisandro Dalcin   PetscErrorCode ierr;
4820598e1a2SLisandro Dalcin 
4830598e1a2SLisandro Dalcin   PetscFunctionBegin;
4840598e1a2SLisandro Dalcin   ierr = PetscNew(mesh);CHKERRQ(ierr);
4850598e1a2SLisandro Dalcin   ierr = PetscSegBufferCreate(sizeof(PetscInt), 0, &(*mesh)->segbuf);CHKERRQ(ierr);
4860598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
4870598e1a2SLisandro Dalcin }
4880598e1a2SLisandro Dalcin 
4890598e1a2SLisandro Dalcin static PetscErrorCode GmshMeshDestroy(GmshMesh **mesh)
4900598e1a2SLisandro Dalcin {
4910598e1a2SLisandro Dalcin   PetscErrorCode ierr;
4920598e1a2SLisandro Dalcin 
4930598e1a2SLisandro Dalcin   PetscFunctionBegin;
4940598e1a2SLisandro Dalcin   if (!*mesh) PetscFunctionReturn(0);
4950598e1a2SLisandro Dalcin   ierr = GmshEntitiesDestroy(&(*mesh)->entities);CHKERRQ(ierr);
4960598e1a2SLisandro Dalcin   ierr = GmshNodesDestroy(&(*mesh)->nodelist);CHKERRQ(ierr);
4970598e1a2SLisandro Dalcin   ierr = GmshElementsDestroy(&(*mesh)->elements);CHKERRQ(ierr);
4980598e1a2SLisandro Dalcin   ierr = PetscFree((*mesh)->periodMap);CHKERRQ(ierr);
4990598e1a2SLisandro Dalcin   ierr = PetscFree((*mesh)->vertexMap);CHKERRQ(ierr);
5000598e1a2SLisandro Dalcin   ierr = PetscSegBufferDestroy(&(*mesh)->segbuf);CHKERRQ(ierr);
5010598e1a2SLisandro Dalcin   ierr = PetscFree((*mesh));CHKERRQ(ierr);
5020598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
5030598e1a2SLisandro Dalcin }
5040598e1a2SLisandro Dalcin 
5050598e1a2SLisandro Dalcin static PetscErrorCode GmshReadNodes_v22(GmshFile *gmsh, GmshMesh *mesh)
506de78e4feSLisandro Dalcin {
507698a79b9SLisandro Dalcin   PetscViewer    viewer = gmsh->viewer;
508698a79b9SLisandro Dalcin   PetscBool      byteSwap = gmsh->byteSwap;
509de78e4feSLisandro Dalcin   char           line[PETSC_MAX_PATH_LEN];
5100598e1a2SLisandro Dalcin   int            n, num, nid, snum;
5110598e1a2SLisandro Dalcin   GmshNodes      *nodes;
512de78e4feSLisandro Dalcin   PetscErrorCode ierr;
513de78e4feSLisandro Dalcin 
514de78e4feSLisandro Dalcin   PetscFunctionBegin;
515de78e4feSLisandro Dalcin   ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr);
516698a79b9SLisandro Dalcin   snum = sscanf(line, "%d", &num);
5170598e1a2SLisandro Dalcin   if (snum != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
5180598e1a2SLisandro Dalcin   ierr = GmshNodesCreate(num, &nodes);CHKERRQ(ierr);
5190598e1a2SLisandro Dalcin   mesh->numNodes = num;
5200598e1a2SLisandro Dalcin   mesh->nodelist = nodes;
5210598e1a2SLisandro Dalcin   for (n = 0; n < num; ++n) {
5220598e1a2SLisandro Dalcin     double *xyz = nodes->xyz + n*3;
52311c56cb0SLisandro Dalcin     ierr = PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM);CHKERRQ(ierr);
52411c56cb0SLisandro Dalcin     ierr = PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE);CHKERRQ(ierr);
5250598e1a2SLisandro Dalcin     if (byteSwap) {ierr = PetscByteSwap(&nid, PETSC_ENUM, 1);CHKERRQ(ierr);}
52611c56cb0SLisandro Dalcin     if (byteSwap) {ierr = PetscByteSwap(xyz, PETSC_DOUBLE, 3);CHKERRQ(ierr);}
5270598e1a2SLisandro Dalcin     nodes->id[n] = nid;
52811c56cb0SLisandro Dalcin   }
52911c56cb0SLisandro Dalcin   PetscFunctionReturn(0);
53011c56cb0SLisandro Dalcin }
53111c56cb0SLisandro Dalcin 
532de78e4feSLisandro Dalcin /* Gmsh elements can be of any dimension/co-dimension, so we need to traverse the
533de78e4feSLisandro Dalcin    file contents multiple times to figure out the true number of cells and facets
534de78e4feSLisandro Dalcin    in the given mesh. To make this more efficient we read the file contents only
535de78e4feSLisandro Dalcin    once and store them in memory, while determining the true number of cells. */
5360598e1a2SLisandro Dalcin static PetscErrorCode GmshReadElements_v22(GmshFile* gmsh, GmshMesh *mesh)
53711c56cb0SLisandro Dalcin {
538698a79b9SLisandro Dalcin   PetscViewer    viewer = gmsh->viewer;
539698a79b9SLisandro Dalcin   PetscBool      binary = gmsh->binary;
540698a79b9SLisandro Dalcin   PetscBool      byteSwap = gmsh->byteSwap;
541de78e4feSLisandro Dalcin   char           line[PETSC_MAX_PATH_LEN];
5420598e1a2SLisandro Dalcin   int            i, c, p, num, ibuf[1+4+1000], snum;
5430598e1a2SLisandro Dalcin   int            cellType, numElem, numVerts, numNodes, numTags;
544df032b82SMatthew G. Knepley   GmshElement   *elements;
5450598e1a2SLisandro Dalcin   PetscInt      *nodeMap = gmsh->nodeMap;
546df032b82SMatthew G. Knepley   PetscErrorCode ierr;
547df032b82SMatthew G. Knepley 
548df032b82SMatthew G. Knepley   PetscFunctionBegin;
549feb237baSPierre Jolivet   ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr);
550698a79b9SLisandro Dalcin   snum = sscanf(line, "%d", &num);
5510598e1a2SLisandro Dalcin   if (snum != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
5520598e1a2SLisandro Dalcin   ierr = GmshElementsCreate(num, &elements);CHKERRQ(ierr);
5530598e1a2SLisandro Dalcin   mesh->numElems = num;
5540598e1a2SLisandro Dalcin   mesh->elements = elements;
555698a79b9SLisandro Dalcin   for (c = 0; c < num;) {
55611c56cb0SLisandro Dalcin     ierr = PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM);CHKERRQ(ierr);
55711c56cb0SLisandro Dalcin     if (byteSwap) {ierr = PetscByteSwap(ibuf, PETSC_ENUM, 3);CHKERRQ(ierr);}
5580598e1a2SLisandro Dalcin 
5590598e1a2SLisandro Dalcin     cellType = binary ? ibuf[0] : ibuf[1];
5600598e1a2SLisandro Dalcin     numElem  = binary ? ibuf[1] : 1;
561df032b82SMatthew G. Knepley     numTags  = ibuf[2];
5620598e1a2SLisandro Dalcin 
5630598e1a2SLisandro Dalcin     ierr = GmshCellTypeCheck(cellType);CHKERRQ(ierr);
5640598e1a2SLisandro Dalcin     numVerts = GmshCellMap[cellType].numVerts;
5650598e1a2SLisandro Dalcin     numNodes = GmshCellMap[cellType].numNodes;
5660598e1a2SLisandro Dalcin 
567df032b82SMatthew G. Knepley     for (i = 0; i < numElem; ++i, ++c) {
5680598e1a2SLisandro Dalcin       GmshElement *element = elements + c;
5690598e1a2SLisandro Dalcin       const int off = binary ? 0 : 1, nint = 1 + numTags + numNodes - off;
5700598e1a2SLisandro Dalcin       const int *id = ibuf, *nodes = ibuf + 1 + numTags, *tags = ibuf + 1;
5710598e1a2SLisandro Dalcin       ierr = PetscViewerRead(viewer, ibuf+off, nint, NULL, PETSC_ENUM);CHKERRQ(ierr);
5720598e1a2SLisandro Dalcin       if (byteSwap) {ierr = PetscByteSwap(ibuf+off, PETSC_ENUM, nint);CHKERRQ(ierr);}
5730598e1a2SLisandro Dalcin       element->id  = id[0];
5740598e1a2SLisandro Dalcin       element->dim = GmshCellMap[cellType].dim;
5750598e1a2SLisandro Dalcin       element->cellType = cellType;
5760598e1a2SLisandro Dalcin       element->numVerts = numVerts;
5770598e1a2SLisandro Dalcin       element->numNodes = numNodes;
5780598e1a2SLisandro Dalcin       element->numTags  = PetscMin(numTags, 4);
5790598e1a2SLisandro Dalcin       ierr = PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes);CHKERRQ(ierr);
5800598e1a2SLisandro Dalcin       for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]];
5810598e1a2SLisandro Dalcin       for (p = 0; p < element->numTags;  p++) element->tags[p]  = tags[p];
582df032b82SMatthew G. Knepley     }
583df032b82SMatthew G. Knepley   }
584df032b82SMatthew G. Knepley   PetscFunctionReturn(0);
585df032b82SMatthew G. Knepley }
5867d282ae0SMichael Lange 
587de78e4feSLisandro Dalcin /*
588de78e4feSLisandro Dalcin $Entities
589de78e4feSLisandro Dalcin   numPoints(unsigned long) numCurves(unsigned long)
590de78e4feSLisandro Dalcin     numSurfaces(unsigned long) numVolumes(unsigned long)
591de78e4feSLisandro Dalcin   // points
592de78e4feSLisandro Dalcin   tag(int) boxMinX(double) boxMinY(double) boxMinZ(double)
593de78e4feSLisandro Dalcin     boxMaxX(double) boxMaxY(double) boxMaxZ(double)
594de78e4feSLisandro Dalcin     numPhysicals(unsigned long) phyisicalTag[...](int)
595de78e4feSLisandro Dalcin   ...
596de78e4feSLisandro Dalcin   // curves
597de78e4feSLisandro Dalcin   tag(int) boxMinX(double) boxMinY(double) boxMinZ(double)
598de78e4feSLisandro Dalcin      boxMaxX(double) boxMaxY(double) boxMaxZ(double)
599de78e4feSLisandro Dalcin      numPhysicals(unsigned long) physicalTag[...](int)
600de78e4feSLisandro Dalcin      numBREPVert(unsigned long) tagBREPVert[...](int)
601de78e4feSLisandro Dalcin   ...
602de78e4feSLisandro Dalcin   // surfaces
603de78e4feSLisandro Dalcin   tag(int) boxMinX(double) boxMinY(double) boxMinZ(double)
604de78e4feSLisandro Dalcin     boxMaxX(double) boxMaxY(double) boxMaxZ(double)
605de78e4feSLisandro Dalcin     numPhysicals(unsigned long) physicalTag[...](int)
606de78e4feSLisandro Dalcin     numBREPCurve(unsigned long) tagBREPCurve[...](int)
607de78e4feSLisandro Dalcin   ...
608de78e4feSLisandro Dalcin   // volumes
609de78e4feSLisandro Dalcin   tag(int) boxMinX(double) boxMinY(double) boxMinZ(double)
610de78e4feSLisandro Dalcin     boxMaxX(double) boxMaxY(double) boxMaxZ(double)
611de78e4feSLisandro Dalcin     numPhysicals(unsigned long) physicalTag[...](int)
612de78e4feSLisandro Dalcin     numBREPSurfaces(unsigned long) tagBREPSurfaces[...](int)
613de78e4feSLisandro Dalcin   ...
614de78e4feSLisandro Dalcin $EndEntities
615de78e4feSLisandro Dalcin */
6160598e1a2SLisandro Dalcin static PetscErrorCode GmshReadEntities_v40(GmshFile *gmsh, GmshMesh *mesh)
617de78e4feSLisandro Dalcin {
618698a79b9SLisandro Dalcin   PetscViewer    viewer = gmsh->viewer;
619698a79b9SLisandro Dalcin   PetscBool      byteSwap = gmsh->byteSwap;
620698a79b9SLisandro Dalcin   long           index, num, lbuf[4];
621730356f6SLisandro Dalcin   int            dim, eid, numTags, *ibuf, t;
622698a79b9SLisandro Dalcin   PetscInt       count[4], i;
623a5ba3d71SLisandro Dalcin   GmshEntity     *entity = NULL;
624de78e4feSLisandro Dalcin   PetscErrorCode ierr;
625de78e4feSLisandro Dalcin 
626de78e4feSLisandro Dalcin   PetscFunctionBegin;
627698a79b9SLisandro Dalcin   ierr = PetscViewerRead(viewer, lbuf, 4, NULL, PETSC_LONG);CHKERRQ(ierr);
628698a79b9SLisandro Dalcin   if (byteSwap) {ierr = PetscByteSwap(lbuf, PETSC_LONG, 4);CHKERRQ(ierr);}
629698a79b9SLisandro Dalcin   for (i = 0; i < 4; ++i) count[i] = lbuf[i];
6300598e1a2SLisandro Dalcin   ierr = GmshEntitiesCreate(count, &mesh->entities);CHKERRQ(ierr);
631de78e4feSLisandro Dalcin   for (dim = 0; dim < 4; ++dim) {
632730356f6SLisandro Dalcin     for (index = 0; index < count[dim]; ++index) {
633730356f6SLisandro Dalcin       ierr = PetscViewerRead(viewer, &eid, 1, NULL, PETSC_ENUM);CHKERRQ(ierr);
634730356f6SLisandro Dalcin       if (byteSwap) {ierr = PetscByteSwap(&eid, PETSC_ENUM, 1);CHKERRQ(ierr);}
6350598e1a2SLisandro Dalcin       ierr = GmshEntitiesAdd(mesh->entities, (PetscInt)index, dim, eid, &entity);CHKERRQ(ierr);
636de78e4feSLisandro Dalcin       ierr = PetscViewerRead(viewer, entity->bbox, 6, NULL, PETSC_DOUBLE);CHKERRQ(ierr);
637de78e4feSLisandro Dalcin       if (byteSwap) {ierr = PetscByteSwap(entity->bbox, PETSC_DOUBLE, 6);CHKERRQ(ierr);}
638de78e4feSLisandro Dalcin       ierr = PetscViewerRead(viewer, &num, 1, NULL, PETSC_LONG);CHKERRQ(ierr);
639de78e4feSLisandro Dalcin       if (byteSwap) {ierr = PetscByteSwap(&num, PETSC_LONG, 1);CHKERRQ(ierr);}
640698a79b9SLisandro Dalcin       ierr = GmshBufferGet(gmsh, num, sizeof(int), &ibuf);CHKERRQ(ierr);
641de78e4feSLisandro Dalcin       ierr = PetscViewerRead(viewer, ibuf, num, NULL, PETSC_ENUM);CHKERRQ(ierr);
642730356f6SLisandro Dalcin       if (byteSwap) {ierr = PetscByteSwap(ibuf, PETSC_ENUM, num);CHKERRQ(ierr);}
643de78e4feSLisandro Dalcin       entity->numTags = numTags = (int) PetscMin(num, 4);
644de78e4feSLisandro Dalcin       for (t = 0; t < numTags; ++t) entity->tags[t] = ibuf[t];
645de78e4feSLisandro Dalcin       if (dim == 0) continue;
646de78e4feSLisandro Dalcin       ierr = PetscViewerRead(viewer, &num, 1, NULL, PETSC_LONG);CHKERRQ(ierr);
647de78e4feSLisandro Dalcin       if (byteSwap) {ierr = PetscByteSwap(&num, PETSC_LONG, 1);CHKERRQ(ierr);}
648698a79b9SLisandro Dalcin       ierr = GmshBufferGet(gmsh, num, sizeof(int), &ibuf);CHKERRQ(ierr);
649de78e4feSLisandro Dalcin       ierr = PetscViewerRead(viewer, ibuf, num, NULL, PETSC_ENUM);CHKERRQ(ierr);
650730356f6SLisandro Dalcin       if (byteSwap) {ierr = PetscByteSwap(ibuf, PETSC_ENUM, num);CHKERRQ(ierr);}
651de78e4feSLisandro Dalcin     }
652de78e4feSLisandro Dalcin   }
653de78e4feSLisandro Dalcin   PetscFunctionReturn(0);
654de78e4feSLisandro Dalcin }
655de78e4feSLisandro Dalcin 
656de78e4feSLisandro Dalcin /*
657de78e4feSLisandro Dalcin $Nodes
658de78e4feSLisandro Dalcin   numEntityBlocks(unsigned long) numNodes(unsigned long)
659de78e4feSLisandro Dalcin   tagEntity(int) dimEntity(int) typeNode(int) numNodes(unsigned long)
660de78e4feSLisandro Dalcin     tag(int) x(double) y(double) z(double)
661de78e4feSLisandro Dalcin     ...
662de78e4feSLisandro Dalcin   ...
663de78e4feSLisandro Dalcin $EndNodes
664de78e4feSLisandro Dalcin */
6650598e1a2SLisandro Dalcin static PetscErrorCode GmshReadNodes_v40(GmshFile *gmsh, GmshMesh *mesh)
666de78e4feSLisandro Dalcin {
667698a79b9SLisandro Dalcin   PetscViewer    viewer = gmsh->viewer;
668698a79b9SLisandro Dalcin   PetscBool      byteSwap = gmsh->byteSwap;
6690598e1a2SLisandro Dalcin   long           block, node, n, numEntityBlocks, numTotalNodes, numNodes;
670de78e4feSLisandro Dalcin   int            info[3], nid;
6710598e1a2SLisandro Dalcin   GmshNodes      *nodes;
672de78e4feSLisandro Dalcin   PetscErrorCode ierr;
673de78e4feSLisandro Dalcin 
674de78e4feSLisandro Dalcin   PetscFunctionBegin;
675de78e4feSLisandro Dalcin   ierr = PetscViewerRead(viewer, &numEntityBlocks, 1, NULL, PETSC_LONG);CHKERRQ(ierr);
676de78e4feSLisandro Dalcin   if (byteSwap) {ierr = PetscByteSwap(&numEntityBlocks, PETSC_LONG, 1);CHKERRQ(ierr);}
677de78e4feSLisandro Dalcin   ierr = PetscViewerRead(viewer, &numTotalNodes, 1, NULL, PETSC_LONG);CHKERRQ(ierr);
678de78e4feSLisandro Dalcin   if (byteSwap) {ierr = PetscByteSwap(&numTotalNodes, PETSC_LONG, 1);CHKERRQ(ierr);}
6790598e1a2SLisandro Dalcin   ierr = GmshNodesCreate(numTotalNodes, &nodes);CHKERRQ(ierr);
6800598e1a2SLisandro Dalcin   mesh->numNodes = numTotalNodes;
6810598e1a2SLisandro Dalcin   mesh->nodelist = nodes;
6820598e1a2SLisandro Dalcin   for (n = 0, block = 0; block < numEntityBlocks; ++block) {
683de78e4feSLisandro Dalcin     ierr = PetscViewerRead(viewer, info, 3, NULL, PETSC_ENUM);CHKERRQ(ierr);
684de78e4feSLisandro Dalcin     ierr = PetscViewerRead(viewer, &numNodes, 1, NULL, PETSC_LONG);CHKERRQ(ierr);
685de78e4feSLisandro Dalcin     if (byteSwap) {ierr = PetscByteSwap(&numNodes, PETSC_LONG, 1);CHKERRQ(ierr);}
686698a79b9SLisandro Dalcin     if (gmsh->binary) {
687277f51e8SBarry Smith       size_t nbytes = sizeof(int) + 3*sizeof(double);
688277f51e8SBarry Smith       char   *cbuf = NULL; /* dummy value to prevent warning from compiler about possible unitilized value */
689698a79b9SLisandro Dalcin       ierr = GmshBufferGet(gmsh, numNodes, nbytes, &cbuf);CHKERRQ(ierr);
690de78e4feSLisandro Dalcin       ierr = PetscViewerRead(viewer, cbuf, numNodes*nbytes, NULL, PETSC_CHAR);CHKERRQ(ierr);
6910598e1a2SLisandro Dalcin       for (node = 0; node < numNodes; ++node, ++n) {
692de78e4feSLisandro Dalcin         char   *cnid = cbuf + node*nbytes, *cxyz = cnid + sizeof(int);
6930598e1a2SLisandro Dalcin         double *xyz = nodes->xyz + n*3;
69430815ce0SLisandro Dalcin         if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(cnid, PETSC_ENUM, 1);CHKERRQ(ierr);}
69530815ce0SLisandro Dalcin         if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(cxyz, PETSC_DOUBLE, 3);CHKERRQ(ierr);}
696de78e4feSLisandro Dalcin         ierr = PetscMemcpy(&nid, cnid, sizeof(int));CHKERRQ(ierr);
697de78e4feSLisandro Dalcin         ierr = PetscMemcpy(xyz, cxyz, 3*sizeof(double));CHKERRQ(ierr);
698de78e4feSLisandro Dalcin         if (byteSwap) {ierr = PetscByteSwap(&nid, PETSC_ENUM, 1);CHKERRQ(ierr);}
699de78e4feSLisandro Dalcin         if (byteSwap) {ierr = PetscByteSwap(xyz, PETSC_DOUBLE, 3);CHKERRQ(ierr);}
7000598e1a2SLisandro Dalcin         nodes->id[n] = nid;
701de78e4feSLisandro Dalcin       }
702de78e4feSLisandro Dalcin     } else {
7030598e1a2SLisandro Dalcin       for (node = 0; node < numNodes; ++node, ++n) {
7040598e1a2SLisandro Dalcin         double *xyz = nodes->xyz + n*3;
705de78e4feSLisandro Dalcin         ierr = PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM);CHKERRQ(ierr);
706de78e4feSLisandro Dalcin         ierr = PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE);CHKERRQ(ierr);
7070598e1a2SLisandro Dalcin         if (byteSwap) {ierr = PetscByteSwap(&nid, PETSC_ENUM, 1);CHKERRQ(ierr);}
708de78e4feSLisandro Dalcin         if (byteSwap) {ierr = PetscByteSwap(xyz, PETSC_DOUBLE, 3);CHKERRQ(ierr);}
7090598e1a2SLisandro Dalcin         nodes->id[n] = nid;
710de78e4feSLisandro Dalcin       }
711de78e4feSLisandro Dalcin     }
712de78e4feSLisandro Dalcin   }
713de78e4feSLisandro Dalcin   PetscFunctionReturn(0);
714de78e4feSLisandro Dalcin }
715de78e4feSLisandro Dalcin 
716de78e4feSLisandro Dalcin /*
717de78e4feSLisandro Dalcin $Elements
718de78e4feSLisandro Dalcin   numEntityBlocks(unsigned long) numElements(unsigned long)
719de78e4feSLisandro Dalcin   tagEntity(int) dimEntity(int) typeEle(int) numElements(unsigned long)
720de78e4feSLisandro Dalcin     tag(int) numVert[...](int)
721de78e4feSLisandro Dalcin     ...
722de78e4feSLisandro Dalcin   ...
723de78e4feSLisandro Dalcin $EndElements
724de78e4feSLisandro Dalcin */
7250598e1a2SLisandro Dalcin static PetscErrorCode GmshReadElements_v40(GmshFile *gmsh, GmshMesh *mesh)
726de78e4feSLisandro Dalcin {
727698a79b9SLisandro Dalcin   PetscViewer    viewer = gmsh->viewer;
728698a79b9SLisandro Dalcin   PetscBool      byteSwap = gmsh->byteSwap;
729de78e4feSLisandro Dalcin   long           c, block, numEntityBlocks, numTotalElements, elem, numElements;
730de78e4feSLisandro Dalcin   int            p, info[3], *ibuf = NULL;
7310598e1a2SLisandro Dalcin   int            eid, dim, cellType, numVerts, numNodes, numTags;
732a5ba3d71SLisandro Dalcin   GmshEntity     *entity = NULL;
733de78e4feSLisandro Dalcin   GmshElement    *elements;
7340598e1a2SLisandro Dalcin   PetscInt       *nodeMap = gmsh->nodeMap;
735de78e4feSLisandro Dalcin   PetscErrorCode ierr;
736de78e4feSLisandro Dalcin 
737de78e4feSLisandro Dalcin   PetscFunctionBegin;
738de78e4feSLisandro Dalcin   ierr = PetscViewerRead(viewer, &numEntityBlocks, 1, NULL, PETSC_LONG);CHKERRQ(ierr);
739de78e4feSLisandro Dalcin   if (byteSwap) {ierr = PetscByteSwap(&numEntityBlocks, PETSC_LONG, 1);CHKERRQ(ierr);}
740de78e4feSLisandro Dalcin   ierr = PetscViewerRead(viewer, &numTotalElements, 1, NULL, PETSC_LONG);CHKERRQ(ierr);
741de78e4feSLisandro Dalcin   if (byteSwap) {ierr = PetscByteSwap(&numTotalElements, PETSC_LONG, 1);CHKERRQ(ierr);}
7420598e1a2SLisandro Dalcin   ierr = GmshElementsCreate(numTotalElements, &elements);CHKERRQ(ierr);
7430598e1a2SLisandro Dalcin   mesh->numElems = numTotalElements;
7440598e1a2SLisandro Dalcin   mesh->elements = elements;
745de78e4feSLisandro Dalcin   for (c = 0, block = 0; block < numEntityBlocks; ++block) {
746de78e4feSLisandro Dalcin     ierr = PetscViewerRead(viewer, info, 3, NULL, PETSC_ENUM);CHKERRQ(ierr);
747de78e4feSLisandro Dalcin     if (byteSwap) {ierr = PetscByteSwap(info, PETSC_ENUM, 3);CHKERRQ(ierr);}
748de78e4feSLisandro Dalcin     eid = info[0]; dim = info[1]; cellType = info[2];
7490598e1a2SLisandro Dalcin     ierr = GmshEntitiesGet(mesh->entities, dim, eid, &entity);CHKERRQ(ierr);
7500598e1a2SLisandro Dalcin     ierr = GmshCellTypeCheck(cellType);CHKERRQ(ierr);
7510598e1a2SLisandro Dalcin     numVerts = GmshCellMap[cellType].numVerts;
7520598e1a2SLisandro Dalcin     numNodes = GmshCellMap[cellType].numNodes;
753730356f6SLisandro Dalcin     numTags  = entity->numTags;
754de78e4feSLisandro Dalcin     ierr = PetscViewerRead(viewer, &numElements, 1, NULL, PETSC_LONG);CHKERRQ(ierr);
755de78e4feSLisandro Dalcin     if (byteSwap) {ierr = PetscByteSwap(&numElements, PETSC_LONG, 1);CHKERRQ(ierr);}
756698a79b9SLisandro Dalcin     ierr = GmshBufferGet(gmsh, (1+numNodes)*numElements, sizeof(int), &ibuf);CHKERRQ(ierr);
757de78e4feSLisandro Dalcin     ierr = PetscViewerRead(viewer, ibuf, (1+numNodes)*numElements, NULL, PETSC_ENUM);CHKERRQ(ierr);
758de78e4feSLisandro Dalcin     if (byteSwap) {ierr = PetscByteSwap(ibuf, PETSC_ENUM, (1+numNodes)*numElements);CHKERRQ(ierr);}
759de78e4feSLisandro Dalcin     for (elem = 0; elem < numElements; ++elem, ++c) {
760de78e4feSLisandro Dalcin       GmshElement *element = elements + c;
7610598e1a2SLisandro Dalcin       const int *id = ibuf + elem*(1+numNodes), *nodes = id + 1;
7620598e1a2SLisandro Dalcin       element->id  = id[0];
763de78e4feSLisandro Dalcin       element->dim = dim;
764de78e4feSLisandro Dalcin       element->cellType = cellType;
7650598e1a2SLisandro Dalcin       element->numVerts = numVerts;
766de78e4feSLisandro Dalcin       element->numNodes = numNodes;
767de78e4feSLisandro Dalcin       element->numTags  = numTags;
7680598e1a2SLisandro Dalcin       ierr = PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes);CHKERRQ(ierr);
7690598e1a2SLisandro Dalcin       for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]];
7700598e1a2SLisandro Dalcin       for (p = 0; p < element->numTags;  p++) element->tags[p]  = entity->tags[p];
771de78e4feSLisandro Dalcin     }
772de78e4feSLisandro Dalcin   }
773698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
774698a79b9SLisandro Dalcin }
775698a79b9SLisandro Dalcin 
7760598e1a2SLisandro Dalcin static PetscErrorCode GmshReadPeriodic_v40(GmshFile *gmsh, PetscInt periodicMap[])
777698a79b9SLisandro Dalcin {
778698a79b9SLisandro Dalcin   PetscViewer    viewer = gmsh->viewer;
779698a79b9SLisandro Dalcin   int            fileFormat = gmsh->fileFormat;
780698a79b9SLisandro Dalcin   PetscBool      binary = gmsh->binary;
781698a79b9SLisandro Dalcin   PetscBool      byteSwap = gmsh->byteSwap;
782698a79b9SLisandro Dalcin   int            numPeriodic, snum, i;
783698a79b9SLisandro Dalcin   char           line[PETSC_MAX_PATH_LEN];
7840598e1a2SLisandro Dalcin   PetscInt       *nodeMap = gmsh->nodeMap;
785698a79b9SLisandro Dalcin   PetscErrorCode ierr;
786698a79b9SLisandro Dalcin 
787698a79b9SLisandro Dalcin   PetscFunctionBegin;
788698a79b9SLisandro Dalcin   if (fileFormat == 22 || !binary) {
789698a79b9SLisandro Dalcin     ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr);
790698a79b9SLisandro Dalcin     snum = sscanf(line, "%d", &numPeriodic);
7910598e1a2SLisandro Dalcin     if (snum != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
792698a79b9SLisandro Dalcin   } else {
793698a79b9SLisandro Dalcin     ierr = PetscViewerRead(viewer, &numPeriodic, 1, NULL, PETSC_ENUM);CHKERRQ(ierr);
794698a79b9SLisandro Dalcin     if (byteSwap) {ierr = PetscByteSwap(&numPeriodic, PETSC_ENUM, 1);CHKERRQ(ierr);}
795698a79b9SLisandro Dalcin   }
796698a79b9SLisandro Dalcin   for (i = 0; i < numPeriodic; i++) {
7979dddd249SSatish Balay     int    ibuf[3], correspondingDim = -1, correspondingTag = -1, primaryTag = -1, correspondingNode, primaryNode;
798698a79b9SLisandro Dalcin     long   j, nNodes;
799698a79b9SLisandro Dalcin     double affine[16];
800698a79b9SLisandro Dalcin 
801698a79b9SLisandro Dalcin     if (fileFormat == 22 || !binary) {
802698a79b9SLisandro Dalcin       ierr = PetscViewerRead(viewer, line, 3, NULL, PETSC_STRING);CHKERRQ(ierr);
8039dddd249SSatish Balay       snum = sscanf(line, "%d %d %d", &correspondingDim, &correspondingTag, &primaryTag);
8040598e1a2SLisandro Dalcin       if (snum != 3) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
805698a79b9SLisandro Dalcin     } else {
806698a79b9SLisandro Dalcin       ierr = PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM);CHKERRQ(ierr);
807698a79b9SLisandro Dalcin       if (byteSwap) {ierr = PetscByteSwap(ibuf, PETSC_ENUM, 3);CHKERRQ(ierr);}
8089dddd249SSatish Balay       correspondingDim = ibuf[0]; correspondingTag = ibuf[1]; primaryTag = ibuf[2];
809698a79b9SLisandro Dalcin     }
8109dddd249SSatish Balay     (void)correspondingDim; (void)correspondingTag; (void)primaryTag; /* unused */
811698a79b9SLisandro Dalcin 
812698a79b9SLisandro Dalcin     if (fileFormat == 22 || !binary) {
813698a79b9SLisandro Dalcin       ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr);
814698a79b9SLisandro Dalcin       snum = sscanf(line, "%ld", &nNodes);
8154c500f23SPierre Jolivet       if (snum != 1) { /* discard transformation and try again */
816698a79b9SLisandro Dalcin         ierr = PetscViewerRead(viewer, line, -PETSC_MAX_PATH_LEN, NULL, PETSC_STRING);CHKERRQ(ierr);
817698a79b9SLisandro Dalcin         ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr);
818698a79b9SLisandro Dalcin         snum = sscanf(line, "%ld", &nNodes);
8190598e1a2SLisandro Dalcin         if (snum != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
820698a79b9SLisandro Dalcin       }
821698a79b9SLisandro Dalcin     } else {
822698a79b9SLisandro Dalcin       ierr = PetscViewerRead(viewer, &nNodes, 1, NULL, PETSC_LONG);CHKERRQ(ierr);
823698a79b9SLisandro Dalcin       if (byteSwap) {ierr = PetscByteSwap(&nNodes, PETSC_LONG, 1);CHKERRQ(ierr);}
8244c500f23SPierre Jolivet       if (nNodes == -1) { /* discard transformation and try again */
825698a79b9SLisandro Dalcin         ierr = PetscViewerRead(viewer, affine, 16, NULL, PETSC_DOUBLE);CHKERRQ(ierr);
826698a79b9SLisandro Dalcin         ierr = PetscViewerRead(viewer, &nNodes, 1, NULL, PETSC_LONG);CHKERRQ(ierr);
827698a79b9SLisandro Dalcin         if (byteSwap) {ierr = PetscByteSwap(&nNodes, PETSC_LONG, 1);CHKERRQ(ierr);}
828698a79b9SLisandro Dalcin       }
829698a79b9SLisandro Dalcin     }
830698a79b9SLisandro Dalcin 
831698a79b9SLisandro Dalcin     for (j = 0; j < nNodes; j++) {
832698a79b9SLisandro Dalcin       if (fileFormat == 22 || !binary) {
833698a79b9SLisandro Dalcin         ierr = PetscViewerRead(viewer, line, 2, NULL, PETSC_STRING);CHKERRQ(ierr);
8349dddd249SSatish Balay         snum = sscanf(line, "%d %d", &correspondingNode, &primaryNode);
8350598e1a2SLisandro Dalcin         if (snum != 2) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
836698a79b9SLisandro Dalcin       } else {
837698a79b9SLisandro Dalcin         ierr = PetscViewerRead(viewer, ibuf, 2, NULL, PETSC_ENUM);CHKERRQ(ierr);
838698a79b9SLisandro Dalcin         if (byteSwap) {ierr = PetscByteSwap(ibuf, PETSC_ENUM, 2);CHKERRQ(ierr);}
8399dddd249SSatish Balay         correspondingNode = ibuf[0]; primaryNode = ibuf[1];
840698a79b9SLisandro Dalcin       }
8419dddd249SSatish Balay       correspondingNode  = (int) nodeMap[correspondingNode];
8429dddd249SSatish Balay       primaryNode = (int) nodeMap[primaryNode];
8439dddd249SSatish Balay       periodicMap[correspondingNode] = primaryNode;
844698a79b9SLisandro Dalcin     }
845698a79b9SLisandro Dalcin   }
846698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
847698a79b9SLisandro Dalcin }
848698a79b9SLisandro Dalcin 
8490598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
850698a79b9SLisandro Dalcin $Entities
851698a79b9SLisandro Dalcin   numPoints(size_t) numCurves(size_t)
852698a79b9SLisandro Dalcin     numSurfaces(size_t) numVolumes(size_t)
853698a79b9SLisandro Dalcin   pointTag(int) X(double) Y(double) Z(double)
854698a79b9SLisandro Dalcin     numPhysicalTags(size_t) physicalTag(int) ...
855698a79b9SLisandro Dalcin   ...
856698a79b9SLisandro Dalcin   curveTag(int) minX(double) minY(double) minZ(double)
857698a79b9SLisandro Dalcin     maxX(double) maxY(double) maxZ(double)
858698a79b9SLisandro Dalcin     numPhysicalTags(size_t) physicalTag(int) ...
859698a79b9SLisandro Dalcin     numBoundingPoints(size_t) pointTag(int) ...
860698a79b9SLisandro Dalcin   ...
861698a79b9SLisandro Dalcin   surfaceTag(int) minX(double) minY(double) minZ(double)
862698a79b9SLisandro Dalcin     maxX(double) maxY(double) maxZ(double)
863698a79b9SLisandro Dalcin     numPhysicalTags(size_t) physicalTag(int) ...
864698a79b9SLisandro Dalcin     numBoundingCurves(size_t) curveTag(int) ...
865698a79b9SLisandro Dalcin   ...
866698a79b9SLisandro Dalcin   volumeTag(int) minX(double) minY(double) minZ(double)
867698a79b9SLisandro Dalcin     maxX(double) maxY(double) maxZ(double)
868698a79b9SLisandro Dalcin     numPhysicalTags(size_t) physicalTag(int) ...
869698a79b9SLisandro Dalcin     numBoundngSurfaces(size_t) surfaceTag(int) ...
870698a79b9SLisandro Dalcin   ...
871698a79b9SLisandro Dalcin $EndEntities
872698a79b9SLisandro Dalcin */
8730598e1a2SLisandro Dalcin static PetscErrorCode GmshReadEntities_v41(GmshFile *gmsh, GmshMesh *mesh)
874698a79b9SLisandro Dalcin {
875698a79b9SLisandro Dalcin   PetscInt       count[4], index, numTags, i;
876698a79b9SLisandro Dalcin   int            dim, eid, *tags = NULL;
877698a79b9SLisandro Dalcin   GmshEntity     *entity = NULL;
878698a79b9SLisandro Dalcin   PetscErrorCode ierr;
879698a79b9SLisandro Dalcin 
880698a79b9SLisandro Dalcin   PetscFunctionBegin;
881698a79b9SLisandro Dalcin   ierr = GmshReadSize(gmsh, count, 4);CHKERRQ(ierr);
8820598e1a2SLisandro Dalcin   ierr = GmshEntitiesCreate(count, &mesh->entities);CHKERRQ(ierr);
883698a79b9SLisandro Dalcin   for (dim = 0; dim < 4; ++dim) {
884698a79b9SLisandro Dalcin     for (index = 0; index < count[dim]; ++index) {
885698a79b9SLisandro Dalcin       ierr = GmshReadInt(gmsh, &eid, 1);CHKERRQ(ierr);
8860598e1a2SLisandro Dalcin       ierr = GmshEntitiesAdd(mesh->entities, (PetscInt)index, dim, eid, &entity);CHKERRQ(ierr);
887698a79b9SLisandro Dalcin       ierr = GmshReadDouble(gmsh, entity->bbox, (dim == 0) ? 3 : 6);CHKERRQ(ierr);
888698a79b9SLisandro Dalcin       ierr = GmshReadSize(gmsh, &numTags, 1);CHKERRQ(ierr);
889698a79b9SLisandro Dalcin       ierr = GmshBufferGet(gmsh, numTags, sizeof(int), &tags);CHKERRQ(ierr);
890698a79b9SLisandro Dalcin       ierr = GmshReadInt(gmsh, tags, numTags);CHKERRQ(ierr);
891698a79b9SLisandro Dalcin       entity->numTags = PetscMin(numTags, 4);
892698a79b9SLisandro Dalcin       for (i = 0; i < entity->numTags; ++i) entity->tags[i] = tags[i];
893698a79b9SLisandro Dalcin       if (dim == 0) continue;
894698a79b9SLisandro Dalcin       ierr = GmshReadSize(gmsh, &numTags, 1);CHKERRQ(ierr);
895698a79b9SLisandro Dalcin       ierr = GmshBufferGet(gmsh, numTags, sizeof(int), &tags);CHKERRQ(ierr);
896698a79b9SLisandro Dalcin       ierr = GmshReadInt(gmsh, tags, numTags);CHKERRQ(ierr);
897698a79b9SLisandro Dalcin     }
898698a79b9SLisandro Dalcin   }
899698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
900698a79b9SLisandro Dalcin }
901698a79b9SLisandro Dalcin 
90233a088b6SMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
903698a79b9SLisandro Dalcin $Nodes
904698a79b9SLisandro Dalcin   numEntityBlocks(size_t) numNodes(size_t)
905698a79b9SLisandro Dalcin     minNodeTag(size_t) maxNodeTag(size_t)
906698a79b9SLisandro Dalcin   entityDim(int) entityTag(int) parametric(int; 0 or 1) numNodesBlock(size_t)
907698a79b9SLisandro Dalcin     nodeTag(size_t)
908698a79b9SLisandro Dalcin     ...
909698a79b9SLisandro Dalcin     x(double) y(double) z(double)
910698a79b9SLisandro Dalcin        < u(double; if parametric and entityDim = 1 or entityDim = 2) >
911698a79b9SLisandro Dalcin        < v(double; if parametric and entityDim = 2) >
912698a79b9SLisandro Dalcin     ...
913698a79b9SLisandro Dalcin   ...
914698a79b9SLisandro Dalcin $EndNodes
915698a79b9SLisandro Dalcin */
9160598e1a2SLisandro Dalcin static PetscErrorCode GmshReadNodes_v41(GmshFile *gmsh, GmshMesh *mesh)
917698a79b9SLisandro Dalcin {
918698a79b9SLisandro Dalcin   int            info[3];
9190598e1a2SLisandro Dalcin   PetscInt       sizes[4], numEntityBlocks, numNodes, numNodesBlock = 0, block, node;
9200598e1a2SLisandro Dalcin   GmshNodes      *nodes;
921698a79b9SLisandro Dalcin   PetscErrorCode ierr;
922698a79b9SLisandro Dalcin 
923698a79b9SLisandro Dalcin   PetscFunctionBegin;
924698a79b9SLisandro Dalcin   ierr = GmshReadSize(gmsh, sizes, 4);CHKERRQ(ierr);
9250598e1a2SLisandro Dalcin   numEntityBlocks = sizes[0]; numNodes = sizes[1];
9260598e1a2SLisandro Dalcin   ierr = GmshNodesCreate(numNodes, &nodes);CHKERRQ(ierr);
9270598e1a2SLisandro Dalcin   mesh->numNodes = numNodes;
9280598e1a2SLisandro Dalcin   mesh->nodelist = nodes;
929698a79b9SLisandro Dalcin   for (block = 0, node = 0; block < numEntityBlocks; ++block, node += numNodesBlock) {
930698a79b9SLisandro Dalcin     ierr = GmshReadInt(gmsh, info, 3);CHKERRQ(ierr);
931698a79b9SLisandro Dalcin     if (info[2] != 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Parametric coordinates not supported");
9320598e1a2SLisandro Dalcin     ierr = GmshReadSize(gmsh, &numNodesBlock, 1);CHKERRQ(ierr);
9330598e1a2SLisandro Dalcin     ierr = GmshReadSize(gmsh, nodes->id+node, numNodesBlock);CHKERRQ(ierr);
9340598e1a2SLisandro Dalcin     ierr = GmshReadDouble(gmsh, nodes->xyz+node*3, numNodesBlock*3);CHKERRQ(ierr);
935698a79b9SLisandro Dalcin   }
9360598e1a2SLisandro Dalcin   gmsh->nodeStart = sizes[2];
9370598e1a2SLisandro Dalcin   gmsh->nodeEnd   = sizes[3]+1;
938698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
939698a79b9SLisandro Dalcin }
940698a79b9SLisandro Dalcin 
94133a088b6SMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
942698a79b9SLisandro Dalcin $Elements
943698a79b9SLisandro Dalcin   numEntityBlocks(size_t) numElements(size_t)
944698a79b9SLisandro Dalcin     minElementTag(size_t) maxElementTag(size_t)
945698a79b9SLisandro Dalcin   entityDim(int) entityTag(int) elementType(int; see below) numElementsBlock(size_t)
946698a79b9SLisandro Dalcin     elementTag(size_t) nodeTag(size_t) ...
947698a79b9SLisandro Dalcin     ...
948698a79b9SLisandro Dalcin   ...
949698a79b9SLisandro Dalcin $EndElements
950698a79b9SLisandro Dalcin */
9510598e1a2SLisandro Dalcin static PetscErrorCode GmshReadElements_v41(GmshFile *gmsh, GmshMesh *mesh)
952698a79b9SLisandro Dalcin {
9530598e1a2SLisandro Dalcin   int            info[3], eid, dim, cellType;
9540598e1a2SLisandro Dalcin   PetscInt       sizes[4], *ibuf = NULL, numEntityBlocks, numElements, numBlockElements, numVerts, numNodes, numTags, block, elem, c, p;
955698a79b9SLisandro Dalcin   GmshEntity     *entity = NULL;
956698a79b9SLisandro Dalcin   GmshElement    *elements;
9570598e1a2SLisandro Dalcin   PetscInt       *nodeMap = gmsh->nodeMap;
958698a79b9SLisandro Dalcin   PetscErrorCode ierr;
959698a79b9SLisandro Dalcin 
960698a79b9SLisandro Dalcin   PetscFunctionBegin;
961698a79b9SLisandro Dalcin   ierr = GmshReadSize(gmsh, sizes, 4);CHKERRQ(ierr);
962698a79b9SLisandro Dalcin   numEntityBlocks = sizes[0]; numElements = sizes[1];
9630598e1a2SLisandro Dalcin   ierr = GmshElementsCreate(numElements, &elements);CHKERRQ(ierr);
9640598e1a2SLisandro Dalcin   mesh->numElems = numElements;
9650598e1a2SLisandro Dalcin   mesh->elements = elements;
966698a79b9SLisandro Dalcin   for (c = 0, block = 0; block < numEntityBlocks; ++block) {
967698a79b9SLisandro Dalcin     ierr = GmshReadInt(gmsh, info, 3);CHKERRQ(ierr);
968698a79b9SLisandro Dalcin     dim = info[0]; eid = info[1]; cellType = info[2];
9690598e1a2SLisandro Dalcin     ierr = GmshEntitiesGet(mesh->entities, dim, eid, &entity);CHKERRQ(ierr);
9700598e1a2SLisandro Dalcin     ierr = GmshCellTypeCheck(cellType);CHKERRQ(ierr);
9710598e1a2SLisandro Dalcin     numVerts = GmshCellMap[cellType].numVerts;
9720598e1a2SLisandro Dalcin     numNodes = GmshCellMap[cellType].numNodes;
973698a79b9SLisandro Dalcin     numTags  = entity->numTags;
974698a79b9SLisandro Dalcin     ierr = GmshReadSize(gmsh, &numBlockElements, 1);CHKERRQ(ierr);
975698a79b9SLisandro Dalcin     ierr = GmshBufferGet(gmsh, (1+numNodes)*numBlockElements, sizeof(PetscInt), &ibuf);CHKERRQ(ierr);
976698a79b9SLisandro Dalcin     ierr = GmshReadSize(gmsh, ibuf, (1+numNodes)*numBlockElements);CHKERRQ(ierr);
977698a79b9SLisandro Dalcin     for (elem = 0; elem < numBlockElements; ++elem, ++c) {
978698a79b9SLisandro Dalcin       GmshElement *element = elements + c;
9790598e1a2SLisandro Dalcin       const PetscInt *id = ibuf + elem*(1+numNodes), *nodes = id + 1;
980698a79b9SLisandro Dalcin       element->id  = id[0];
981698a79b9SLisandro Dalcin       element->dim = dim;
982698a79b9SLisandro Dalcin       element->cellType = cellType;
9830598e1a2SLisandro Dalcin       element->numVerts = numVerts;
984698a79b9SLisandro Dalcin       element->numNodes = numNodes;
985698a79b9SLisandro Dalcin       element->numTags  = numTags;
9860598e1a2SLisandro Dalcin       ierr = PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes);CHKERRQ(ierr);
9870598e1a2SLisandro Dalcin       for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]];
9880598e1a2SLisandro Dalcin       for (p = 0; p < element->numTags;  p++) element->tags[p]  = entity->tags[p];
989698a79b9SLisandro Dalcin     }
990698a79b9SLisandro Dalcin   }
991698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
992698a79b9SLisandro Dalcin }
993698a79b9SLisandro Dalcin 
9940598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
995698a79b9SLisandro Dalcin $Periodic
996698a79b9SLisandro Dalcin   numPeriodicLinks(size_t)
9979dddd249SSatish Balay   entityDim(int) entityTag(int) entityTagPrimary(int)
998698a79b9SLisandro Dalcin   numAffine(size_t) value(double) ...
999698a79b9SLisandro Dalcin   numCorrespondingNodes(size_t)
10009dddd249SSatish Balay     nodeTag(size_t) nodeTagPrimary(size_t)
1001698a79b9SLisandro Dalcin     ...
1002698a79b9SLisandro Dalcin   ...
1003698a79b9SLisandro Dalcin $EndPeriodic
1004698a79b9SLisandro Dalcin */
10050598e1a2SLisandro Dalcin static PetscErrorCode GmshReadPeriodic_v41(GmshFile *gmsh, PetscInt periodicMap[])
1006698a79b9SLisandro Dalcin {
1007698a79b9SLisandro Dalcin   int            info[3];
1008698a79b9SLisandro Dalcin   double         dbuf[16];
10090598e1a2SLisandro Dalcin   PetscInt       numPeriodicLinks, numAffine, numCorrespondingNodes, *nodeTags = NULL, link, node;
10100598e1a2SLisandro Dalcin   PetscInt       *nodeMap = gmsh->nodeMap;
1011698a79b9SLisandro Dalcin   PetscErrorCode ierr;
1012698a79b9SLisandro Dalcin 
1013698a79b9SLisandro Dalcin   PetscFunctionBegin;
1014698a79b9SLisandro Dalcin   ierr = GmshReadSize(gmsh, &numPeriodicLinks, 1);CHKERRQ(ierr);
1015698a79b9SLisandro Dalcin   for (link = 0; link < numPeriodicLinks; ++link) {
1016698a79b9SLisandro Dalcin     ierr = GmshReadInt(gmsh, info, 3);CHKERRQ(ierr);
1017698a79b9SLisandro Dalcin     ierr = GmshReadSize(gmsh, &numAffine, 1);CHKERRQ(ierr);
1018698a79b9SLisandro Dalcin     ierr = GmshReadDouble(gmsh, dbuf, numAffine);CHKERRQ(ierr);
1019698a79b9SLisandro Dalcin     ierr = GmshReadSize(gmsh, &numCorrespondingNodes, 1);CHKERRQ(ierr);
1020698a79b9SLisandro Dalcin     ierr = GmshBufferGet(gmsh, numCorrespondingNodes, sizeof(PetscInt), &nodeTags);CHKERRQ(ierr);
1021698a79b9SLisandro Dalcin     ierr = GmshReadSize(gmsh, nodeTags, numCorrespondingNodes*2);CHKERRQ(ierr);
1022698a79b9SLisandro Dalcin     for (node = 0; node < numCorrespondingNodes; ++node) {
10239dddd249SSatish Balay       PetscInt correspondingNode = nodeMap[nodeTags[node*2+0]];
10249dddd249SSatish Balay       PetscInt primaryNode = nodeMap[nodeTags[node*2+1]];
10259dddd249SSatish Balay       periodicMap[correspondingNode] = primaryNode;
1026698a79b9SLisandro Dalcin     }
1027698a79b9SLisandro Dalcin   }
1028698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
1029698a79b9SLisandro Dalcin }
1030698a79b9SLisandro Dalcin 
10310598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
1032d6689ca9SLisandro Dalcin $MeshFormat // same as MSH version 2
1033d6689ca9SLisandro Dalcin   version(ASCII double; currently 4.1)
1034d6689ca9SLisandro Dalcin   file-type(ASCII int; 0 for ASCII mode, 1 for binary mode)
1035d6689ca9SLisandro Dalcin   data-size(ASCII int; sizeof(size_t))
1036d6689ca9SLisandro Dalcin   < int with value one; only in binary mode, to detect endianness >
1037d6689ca9SLisandro Dalcin $EndMeshFormat
1038d6689ca9SLisandro Dalcin */
10390598e1a2SLisandro Dalcin static PetscErrorCode GmshReadMeshFormat(GmshFile *gmsh)
1040698a79b9SLisandro Dalcin {
1041698a79b9SLisandro Dalcin   char           line[PETSC_MAX_PATH_LEN];
1042698a79b9SLisandro Dalcin   int            snum, fileType, fileFormat, dataSize, checkEndian;
1043698a79b9SLisandro Dalcin   float          version;
1044698a79b9SLisandro Dalcin   PetscErrorCode ierr;
1045698a79b9SLisandro Dalcin 
1046698a79b9SLisandro Dalcin   PetscFunctionBegin;
1047698a79b9SLisandro Dalcin   ierr = GmshReadString(gmsh, line, 3);CHKERRQ(ierr);
1048698a79b9SLisandro Dalcin   snum = sscanf(line, "%f %d %d", &version, &fileType, &dataSize);
10490598e1a2SLisandro Dalcin   if (snum != 3) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line);
10500598e1a2SLisandro Dalcin   if (version < 2.2) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at least 2.2", (double)version);
10510598e1a2SLisandro Dalcin   if ((int)version == 3) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f not supported", (double)version);
10520598e1a2SLisandro Dalcin   if (version > 4.1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at most 4.1", (double)version);
10530598e1a2SLisandro Dalcin   if (gmsh->binary && !fileType) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Viewer is binary but Gmsh file is ASCII");
10540598e1a2SLisandro Dalcin   if (!gmsh->binary && fileType) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Viewer is ASCII but Gmsh file is binary");
1055af7a0b9fSSatish Balay   fileFormat = (int)roundf(version*10);
10560598e1a2SLisandro Dalcin   if (fileFormat <= 40 && dataSize != sizeof(double)) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Data size %d is not valid for a Gmsh file", dataSize);
10570598e1a2SLisandro Dalcin   if (fileFormat >= 41 && dataSize != sizeof(int) && dataSize != sizeof(PetscInt64)) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Data size %d is not valid for a Gmsh file", dataSize);
1058698a79b9SLisandro Dalcin   gmsh->fileFormat = fileFormat;
1059698a79b9SLisandro Dalcin   gmsh->dataSize = dataSize;
1060698a79b9SLisandro Dalcin   gmsh->byteSwap = PETSC_FALSE;
1061698a79b9SLisandro Dalcin   if (gmsh->binary) {
1062698a79b9SLisandro Dalcin     ierr = GmshReadInt(gmsh, &checkEndian, 1);CHKERRQ(ierr);
1063698a79b9SLisandro Dalcin     if (checkEndian != 1) {
1064698a79b9SLisandro Dalcin       ierr = PetscByteSwap(&checkEndian, PETSC_ENUM, 1);CHKERRQ(ierr);
10650598e1a2SLisandro Dalcin       if (checkEndian != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to detect endianness in Gmsh file header: %s", line);
1066698a79b9SLisandro Dalcin       gmsh->byteSwap = PETSC_TRUE;
1067698a79b9SLisandro Dalcin     }
1068698a79b9SLisandro Dalcin   }
1069698a79b9SLisandro Dalcin   PetscFunctionReturn(0);
1070698a79b9SLisandro Dalcin }
1071698a79b9SLisandro Dalcin 
10721f643af3SLisandro Dalcin /*
10731f643af3SLisandro Dalcin PhysicalNames
10741f643af3SLisandro Dalcin   numPhysicalNames(ASCII int)
10751f643af3SLisandro Dalcin   dimension(ASCII int) physicalTag(ASCII int) "name"(127 characters max)
10761f643af3SLisandro Dalcin   ...
10771f643af3SLisandro Dalcin $EndPhysicalNames
10781f643af3SLisandro Dalcin */
10790598e1a2SLisandro Dalcin static PetscErrorCode GmshReadPhysicalNames(GmshFile *gmsh)
1080698a79b9SLisandro Dalcin {
10811f643af3SLisandro Dalcin   char           line[PETSC_MAX_PATH_LEN], name[128+2], *p, *q;
10821f643af3SLisandro Dalcin   int            snum, numRegions, region, dim, tag;
1083698a79b9SLisandro Dalcin   PetscErrorCode ierr;
1084698a79b9SLisandro Dalcin 
1085698a79b9SLisandro Dalcin   PetscFunctionBegin;
1086698a79b9SLisandro Dalcin   ierr = GmshReadString(gmsh, line, 1);CHKERRQ(ierr);
1087698a79b9SLisandro Dalcin   snum = sscanf(line, "%d", &numRegions);
10880598e1a2SLisandro Dalcin   if (snum != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
1089698a79b9SLisandro Dalcin   for (region = 0; region < numRegions; ++region) {
10901f643af3SLisandro Dalcin     ierr = GmshReadString(gmsh, line, 2);CHKERRQ(ierr);
10911f643af3SLisandro Dalcin     snum = sscanf(line, "%d %d", &dim, &tag);
10920598e1a2SLisandro Dalcin     if (snum != 2) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
10931f643af3SLisandro Dalcin     ierr = GmshReadString(gmsh, line, -(PetscInt)sizeof(line));CHKERRQ(ierr);
10941f643af3SLisandro Dalcin     ierr = PetscStrchr(line, '"', &p);CHKERRQ(ierr);
10950598e1a2SLisandro Dalcin     if (!p) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
10961f643af3SLisandro Dalcin     ierr = PetscStrrchr(line, '"', &q);CHKERRQ(ierr);
10970598e1a2SLisandro Dalcin     if (q == p) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
10981f643af3SLisandro Dalcin     ierr = PetscStrncpy(name, p+1, (size_t)(q-p-1));CHKERRQ(ierr);
1099698a79b9SLisandro Dalcin   }
1100de78e4feSLisandro Dalcin   PetscFunctionReturn(0);
1101de78e4feSLisandro Dalcin }
1102de78e4feSLisandro Dalcin 
11030598e1a2SLisandro Dalcin static PetscErrorCode GmshReadEntities(GmshFile *gmsh, GmshMesh *mesh)
110496ca5757SLisandro Dalcin {
11050598e1a2SLisandro Dalcin   PetscErrorCode ierr;
11060598e1a2SLisandro Dalcin 
11070598e1a2SLisandro Dalcin   PetscFunctionBegin;
11080598e1a2SLisandro Dalcin   switch (gmsh->fileFormat) {
11090598e1a2SLisandro Dalcin   case 41: ierr = GmshReadEntities_v41(gmsh, mesh);CHKERRQ(ierr); break;
11100598e1a2SLisandro Dalcin   default: ierr = GmshReadEntities_v40(gmsh, mesh);CHKERRQ(ierr); break;
111196ca5757SLisandro Dalcin   }
11120598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
11130598e1a2SLisandro Dalcin }
11140598e1a2SLisandro Dalcin 
11150598e1a2SLisandro Dalcin static PetscErrorCode GmshReadNodes(GmshFile *gmsh, GmshMesh *mesh)
11160598e1a2SLisandro Dalcin {
11170598e1a2SLisandro Dalcin   PetscErrorCode ierr;
11180598e1a2SLisandro Dalcin 
11190598e1a2SLisandro Dalcin   PetscFunctionBegin;
11200598e1a2SLisandro Dalcin   switch (gmsh->fileFormat) {
11210598e1a2SLisandro Dalcin   case 41: ierr = GmshReadNodes_v41(gmsh, mesh);CHKERRQ(ierr); break;
11220598e1a2SLisandro Dalcin   case 40: ierr = GmshReadNodes_v40(gmsh, mesh);CHKERRQ(ierr); break;
11230598e1a2SLisandro Dalcin   default: ierr = GmshReadNodes_v22(gmsh, mesh);CHKERRQ(ierr); break;
11240598e1a2SLisandro Dalcin   }
11250598e1a2SLisandro Dalcin 
11260598e1a2SLisandro Dalcin   { /* Gmsh v2.2/v4.0 does not provide min/max node tags */
11270598e1a2SLisandro Dalcin     if (mesh->numNodes > 0 && gmsh->nodeEnd >= gmsh->nodeStart) {
11280598e1a2SLisandro Dalcin       PetscInt  tagMin = PETSC_MAX_INT, tagMax = PETSC_MIN_INT, n;
11290598e1a2SLisandro Dalcin       GmshNodes *nodes = mesh->nodelist;
11300598e1a2SLisandro Dalcin       for (n = 0; n < mesh->numNodes; ++n) {
11310598e1a2SLisandro Dalcin         const PetscInt tag = nodes->id[n];
11320598e1a2SLisandro Dalcin         tagMin = PetscMin(tag, tagMin);
11330598e1a2SLisandro Dalcin         tagMax = PetscMax(tag, tagMax);
11340598e1a2SLisandro Dalcin       }
11350598e1a2SLisandro Dalcin       gmsh->nodeStart = tagMin;
11360598e1a2SLisandro Dalcin       gmsh->nodeEnd   = tagMax+1;
11370598e1a2SLisandro Dalcin     }
11380598e1a2SLisandro Dalcin   }
11390598e1a2SLisandro Dalcin 
11400598e1a2SLisandro Dalcin   { /* Support for sparse node tags */
11410598e1a2SLisandro Dalcin     PetscInt  n, t;
11420598e1a2SLisandro Dalcin     GmshNodes *nodes = mesh->nodelist;
11430598e1a2SLisandro Dalcin     ierr = PetscMalloc1(gmsh->nodeEnd - gmsh->nodeStart, &gmsh->nbuf);CHKERRQ(ierr);
11440598e1a2SLisandro Dalcin     for (t = 0; t < gmsh->nodeEnd - gmsh->nodeStart; ++t) gmsh->nbuf[t] = PETSC_MIN_INT;
11450598e1a2SLisandro Dalcin     gmsh->nodeMap = gmsh->nbuf - gmsh->nodeStart;
11460598e1a2SLisandro Dalcin     for (n = 0; n < mesh->numNodes; ++n) {
11470598e1a2SLisandro Dalcin       const PetscInt tag = nodes->id[n];
11480598e1a2SLisandro Dalcin       if (gmsh->nodeMap[tag] >= 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Repeated node tag %D", tag);
11490598e1a2SLisandro Dalcin       gmsh->nodeMap[tag] = n;
11500598e1a2SLisandro Dalcin     }
11510598e1a2SLisandro Dalcin   }
11520598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
11530598e1a2SLisandro Dalcin }
11540598e1a2SLisandro Dalcin 
11550598e1a2SLisandro Dalcin static PetscErrorCode GmshReadElements(GmshFile *gmsh, GmshMesh *mesh)
11560598e1a2SLisandro Dalcin {
11570598e1a2SLisandro Dalcin   PetscErrorCode ierr;
11580598e1a2SLisandro Dalcin 
11590598e1a2SLisandro Dalcin   PetscFunctionBegin;
11600598e1a2SLisandro Dalcin   switch (gmsh->fileFormat) {
11610598e1a2SLisandro Dalcin   case 41: ierr = GmshReadElements_v41(gmsh, mesh);CHKERRQ(ierr); break;
11620598e1a2SLisandro Dalcin   case 40: ierr = GmshReadElements_v40(gmsh, mesh);CHKERRQ(ierr); break;
11630598e1a2SLisandro Dalcin   default: ierr = GmshReadElements_v22(gmsh, mesh);CHKERRQ(ierr); break;
11640598e1a2SLisandro Dalcin   }
11650598e1a2SLisandro Dalcin 
11660598e1a2SLisandro Dalcin   { /* Reorder elements by codimension and polytope type */
11670598e1a2SLisandro Dalcin     PetscInt    ne = mesh->numElems;
11680598e1a2SLisandro Dalcin     GmshElement *elements = mesh->elements;
1169066ea43fSLisandro Dalcin     PetscInt    keymap[GMSH_NUM_POLYTOPES], nk = 0;
1170066ea43fSLisandro Dalcin     PetscInt    offset[GMSH_NUM_POLYTOPES+1], e, k;
11710598e1a2SLisandro Dalcin 
1172066ea43fSLisandro Dalcin     for (k = 0; k < GMSH_NUM_POLYTOPES; ++k) keymap[k] = PETSC_MIN_INT;
11730598e1a2SLisandro Dalcin     ierr = PetscMemzero(offset,sizeof(offset));CHKERRQ(ierr);
11740598e1a2SLisandro Dalcin 
1175066ea43fSLisandro Dalcin     keymap[GMSH_TET] = nk++;
1176066ea43fSLisandro Dalcin     keymap[GMSH_HEX] = nk++;
1177066ea43fSLisandro Dalcin     keymap[GMSH_PRI] = nk++;
1178066ea43fSLisandro Dalcin     keymap[GMSH_PYR] = nk++;
1179066ea43fSLisandro Dalcin     keymap[GMSH_TRI] = nk++;
1180066ea43fSLisandro Dalcin     keymap[GMSH_QUA] = nk++;
1181066ea43fSLisandro Dalcin     keymap[GMSH_SEG] = nk++;
1182066ea43fSLisandro Dalcin     keymap[GMSH_VTX] = nk++;
11830598e1a2SLisandro Dalcin 
11840598e1a2SLisandro Dalcin     ierr = GmshElementsCreate(mesh->numElems, &mesh->elements);CHKERRQ(ierr);
11850598e1a2SLisandro Dalcin #define key(eid) keymap[GmshCellMap[elements[(eid)].cellType].polytope]
11860598e1a2SLisandro Dalcin     for (e = 0; e < ne; ++e) offset[1+key(e)]++;
11870598e1a2SLisandro Dalcin     for (k = 1; k < nk; ++k) offset[k] += offset[k-1];
11880598e1a2SLisandro Dalcin     for (e = 0; e < ne; ++e) mesh->elements[offset[key(e)]++] = elements[e];
11890598e1a2SLisandro Dalcin #undef key
11900598e1a2SLisandro Dalcin     ierr = GmshElementsDestroy(&elements);CHKERRQ(ierr);
1191066ea43fSLisandro Dalcin   }
11920598e1a2SLisandro Dalcin 
1193066ea43fSLisandro Dalcin   { /* Mesh dimension and order */
1194066ea43fSLisandro Dalcin     GmshElement *elem = mesh->numElems ? mesh->elements : NULL;
1195066ea43fSLisandro Dalcin     mesh->dim   = elem ? GmshCellMap[elem->cellType].dim   : 0;
1196066ea43fSLisandro Dalcin     mesh->order = elem ? GmshCellMap[elem->cellType].order : 0;
11970598e1a2SLisandro Dalcin   }
11980598e1a2SLisandro Dalcin 
11990598e1a2SLisandro Dalcin   {
12000598e1a2SLisandro Dalcin     PetscBT  vtx;
12010598e1a2SLisandro Dalcin     PetscInt dim = mesh->dim, e, n, v;
12020598e1a2SLisandro Dalcin 
12030598e1a2SLisandro Dalcin     ierr = PetscBTCreate(mesh->numNodes, &vtx);CHKERRQ(ierr);
12040598e1a2SLisandro Dalcin 
12050598e1a2SLisandro Dalcin     /* Compute number of cells and set of vertices */
12060598e1a2SLisandro Dalcin     mesh->numCells = 0;
12070598e1a2SLisandro Dalcin     for (e = 0; e < mesh->numElems; ++e) {
12080598e1a2SLisandro Dalcin       GmshElement *elem = mesh->elements + e;
12090598e1a2SLisandro Dalcin       if (elem->dim == dim && dim > 0) mesh->numCells++;
12100598e1a2SLisandro Dalcin       for (v = 0; v < elem->numVerts; v++) {
12110598e1a2SLisandro Dalcin         ierr = PetscBTSet(vtx, elem->nodes[v]);CHKERRQ(ierr);
12120598e1a2SLisandro Dalcin       }
12130598e1a2SLisandro Dalcin     }
12140598e1a2SLisandro Dalcin 
12150598e1a2SLisandro Dalcin     /* Compute numbering for vertices */
12160598e1a2SLisandro Dalcin     mesh->numVerts = 0;
12170598e1a2SLisandro Dalcin     ierr = PetscMalloc1(mesh->numNodes, &mesh->vertexMap);CHKERRQ(ierr);
12180598e1a2SLisandro Dalcin     for (n = 0; n < mesh->numNodes; ++n)
12190598e1a2SLisandro Dalcin       mesh->vertexMap[n] = PetscBTLookup(vtx, n) ? mesh->numVerts++ : PETSC_MIN_INT;
12200598e1a2SLisandro Dalcin 
12210598e1a2SLisandro Dalcin     ierr = PetscBTDestroy(&vtx);CHKERRQ(ierr);
12220598e1a2SLisandro Dalcin   }
12230598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
12240598e1a2SLisandro Dalcin }
12250598e1a2SLisandro Dalcin 
12260598e1a2SLisandro Dalcin static PetscErrorCode GmshReadPeriodic(GmshFile *gmsh, GmshMesh *mesh)
12270598e1a2SLisandro Dalcin {
12280598e1a2SLisandro Dalcin   PetscInt       n;
12290598e1a2SLisandro Dalcin   PetscErrorCode ierr;
12300598e1a2SLisandro Dalcin 
12310598e1a2SLisandro Dalcin   PetscFunctionBegin;
12320598e1a2SLisandro Dalcin   ierr = PetscMalloc1(mesh->numNodes, &mesh->periodMap);CHKERRQ(ierr);
12330598e1a2SLisandro Dalcin   for (n = 0; n < mesh->numNodes; ++n) mesh->periodMap[n] = n;
12340598e1a2SLisandro Dalcin   switch (gmsh->fileFormat) {
12350598e1a2SLisandro Dalcin   case 41: ierr = GmshReadPeriodic_v41(gmsh, mesh->periodMap);CHKERRQ(ierr); break;
12360598e1a2SLisandro Dalcin   default: ierr = GmshReadPeriodic_v40(gmsh, mesh->periodMap);CHKERRQ(ierr); break;
12370598e1a2SLisandro Dalcin   }
12380598e1a2SLisandro Dalcin 
12399dddd249SSatish Balay   /* Find canonical primary nodes */
12400598e1a2SLisandro Dalcin   for (n = 0; n < mesh->numNodes; ++n)
12410598e1a2SLisandro Dalcin     while (mesh->periodMap[n] != mesh->periodMap[mesh->periodMap[n]])
12420598e1a2SLisandro Dalcin       mesh->periodMap[n] = mesh->periodMap[mesh->periodMap[n]];
12430598e1a2SLisandro Dalcin 
12449dddd249SSatish Balay   /* Renumber vertices (filter out correspondings) */
12450598e1a2SLisandro Dalcin   mesh->numVerts = 0;
12460598e1a2SLisandro Dalcin   for (n = 0; n < mesh->numNodes; ++n)
12470598e1a2SLisandro Dalcin     if (mesh->vertexMap[n] >= 0)   /* is vertex */
12489dddd249SSatish Balay       if (mesh->periodMap[n] == n) /* is primary */
12490598e1a2SLisandro Dalcin         mesh->vertexMap[n] = mesh->numVerts++;
12500598e1a2SLisandro Dalcin   for (n = 0; n < mesh->numNodes; ++n)
12510598e1a2SLisandro Dalcin     if (mesh->vertexMap[n] >= 0)   /* is vertex */
12529dddd249SSatish Balay       if (mesh->periodMap[n] != n) /* is corresponding  */
12530598e1a2SLisandro Dalcin         mesh->vertexMap[n] = mesh->vertexMap[mesh->periodMap[n]];
12540598e1a2SLisandro Dalcin   PetscFunctionReturn(0);
12550598e1a2SLisandro Dalcin }
12560598e1a2SLisandro Dalcin 
1257066ea43fSLisandro Dalcin #define DM_POLYTOPE_VERTEX  DM_POLYTOPE_POINT
1258066ea43fSLisandro Dalcin #define DM_POLYTOPE_PYRAMID DM_POLYTOPE_UNKNOWN
1259066ea43fSLisandro Dalcin static const DMPolytopeType DMPolytopeMap[] = {
1260066ea43fSLisandro Dalcin   /* GMSH_VTX */ DM_POLYTOPE_VERTEX,
1261066ea43fSLisandro Dalcin   /* GMSH_SEG */ DM_POLYTOPE_SEGMENT,
1262066ea43fSLisandro Dalcin   /* GMSH_TRI */ DM_POLYTOPE_TRIANGLE,
1263066ea43fSLisandro Dalcin   /* GMSH_QUA */ DM_POLYTOPE_QUADRILATERAL,
1264066ea43fSLisandro Dalcin   /* GMSH_TET */ DM_POLYTOPE_TETRAHEDRON,
1265066ea43fSLisandro Dalcin   /* GMSH_HEX */ DM_POLYTOPE_HEXAHEDRON,
1266066ea43fSLisandro Dalcin   /* GMSH_PRI */ DM_POLYTOPE_TRI_PRISM,
1267066ea43fSLisandro Dalcin   /* GMSH_PYR */ DM_POLYTOPE_PYRAMID,
1268066ea43fSLisandro Dalcin   DM_POLYTOPE_UNKNOWN
1269066ea43fSLisandro Dalcin };
12700598e1a2SLisandro Dalcin 
12710598e1a2SLisandro Dalcin PETSC_STATIC_INLINE DMPolytopeType DMPolytopeTypeFromGmsh(PetscInt cellType)
12720598e1a2SLisandro Dalcin {
1273066ea43fSLisandro Dalcin   return DMPolytopeMap[GmshCellMap[cellType].polytope];
1274066ea43fSLisandro Dalcin }
1275066ea43fSLisandro Dalcin 
1276066ea43fSLisandro Dalcin static PetscErrorCode GmshCreateFE(MPI_Comm comm, const char prefix[], PetscBool isSimplex, PetscBool continuity, PetscDTNodeType nodeType, PetscInt dim, PetscInt Nc, PetscInt k, PetscFE *fem)
1277066ea43fSLisandro Dalcin {
1278066ea43fSLisandro Dalcin   DM              K;
1279066ea43fSLisandro Dalcin   PetscSpace      P;
1280066ea43fSLisandro Dalcin   PetscDualSpace  Q;
1281066ea43fSLisandro Dalcin   PetscQuadrature q, fq;
1282066ea43fSLisandro Dalcin   PetscBool       isTensor = isSimplex ? PETSC_FALSE : PETSC_TRUE;
1283066ea43fSLisandro Dalcin   PetscBool       endpoint = PETSC_TRUE;
1284066ea43fSLisandro Dalcin   char            name[32];
1285066ea43fSLisandro Dalcin   PetscErrorCode  ierr;
1286066ea43fSLisandro Dalcin 
1287066ea43fSLisandro Dalcin   PetscFunctionBegin;
1288066ea43fSLisandro Dalcin   /* Create space */
1289066ea43fSLisandro Dalcin   ierr = PetscSpaceCreate(comm, &P);CHKERRQ(ierr);
1290066ea43fSLisandro Dalcin   ierr = PetscSpaceSetType(P, PETSCSPACEPOLYNOMIAL);CHKERRQ(ierr);
1291066ea43fSLisandro Dalcin   ierr = PetscSpacePolynomialSetTensor(P, isTensor);CHKERRQ(ierr);
1292066ea43fSLisandro Dalcin   ierr = PetscSpaceSetNumComponents(P, Nc);CHKERRQ(ierr);
1293066ea43fSLisandro Dalcin   ierr = PetscSpaceSetNumVariables(P, dim);CHKERRQ(ierr);
1294066ea43fSLisandro Dalcin   ierr = PetscSpaceSetDegree(P, k, PETSC_DETERMINE);CHKERRQ(ierr);
1295066ea43fSLisandro Dalcin   if (prefix) {
1296066ea43fSLisandro Dalcin     ierr = PetscObjectSetOptionsPrefix((PetscObject) P, prefix);CHKERRQ(ierr);
1297066ea43fSLisandro Dalcin     ierr = PetscSpaceSetFromOptions(P);CHKERRQ(ierr);
1298066ea43fSLisandro Dalcin     ierr = PetscObjectSetOptionsPrefix((PetscObject) P, NULL);CHKERRQ(ierr);
1299066ea43fSLisandro Dalcin     ierr = PetscSpaceGetDegree(P, &k, NULL);CHKERRQ(ierr);
1300066ea43fSLisandro Dalcin   }
1301066ea43fSLisandro Dalcin   ierr = PetscSpaceSetUp(P);CHKERRQ(ierr);
1302066ea43fSLisandro Dalcin   /* Create dual space */
1303066ea43fSLisandro Dalcin   ierr = PetscDualSpaceCreate(comm, &Q);CHKERRQ(ierr);
1304066ea43fSLisandro Dalcin   ierr = PetscDualSpaceSetType(Q, PETSCDUALSPACELAGRANGE);CHKERRQ(ierr);
1305066ea43fSLisandro Dalcin   ierr = PetscDualSpaceLagrangeSetTensor(Q, isTensor);CHKERRQ(ierr);
1306066ea43fSLisandro Dalcin   ierr = PetscDualSpaceLagrangeSetContinuity(Q, continuity);CHKERRQ(ierr);
1307066ea43fSLisandro Dalcin   ierr = PetscDualSpaceLagrangeSetNodeType(Q, nodeType, endpoint, 0);CHKERRQ(ierr);
1308066ea43fSLisandro Dalcin   ierr = PetscDualSpaceSetNumComponents(Q, Nc);CHKERRQ(ierr);
1309066ea43fSLisandro Dalcin   ierr = PetscDualSpaceSetOrder(Q, k);CHKERRQ(ierr);
1310066ea43fSLisandro Dalcin   ierr = PetscDualSpaceCreateReferenceCell(Q, dim, isSimplex, &K);CHKERRQ(ierr);
1311066ea43fSLisandro Dalcin   ierr = PetscDualSpaceSetDM(Q, K);CHKERRQ(ierr);
1312066ea43fSLisandro Dalcin   ierr = DMDestroy(&K);CHKERRQ(ierr);
1313066ea43fSLisandro Dalcin   if (prefix) {
1314066ea43fSLisandro Dalcin     ierr = PetscObjectSetOptionsPrefix((PetscObject) Q, prefix);CHKERRQ(ierr);
1315066ea43fSLisandro Dalcin     ierr = PetscDualSpaceSetFromOptions(Q);CHKERRQ(ierr);
1316066ea43fSLisandro Dalcin     ierr = PetscObjectSetOptionsPrefix((PetscObject) Q, NULL);CHKERRQ(ierr);
1317066ea43fSLisandro Dalcin   }
1318066ea43fSLisandro Dalcin   ierr = PetscDualSpaceSetUp(Q);CHKERRQ(ierr);
1319066ea43fSLisandro Dalcin   /* Create quadrature */
1320066ea43fSLisandro Dalcin   if (isSimplex) {
1321066ea43fSLisandro Dalcin     ierr = PetscDTStroudConicalQuadrature(dim,   1, k+1, -1, +1, &q);CHKERRQ(ierr);
1322066ea43fSLisandro Dalcin     ierr = PetscDTStroudConicalQuadrature(dim-1, 1, k+1, -1, +1, &fq);CHKERRQ(ierr);
1323066ea43fSLisandro Dalcin   } else {
1324066ea43fSLisandro Dalcin     ierr = PetscDTGaussTensorQuadrature(dim,   1, k+1, -1, +1, &q);CHKERRQ(ierr);
1325066ea43fSLisandro Dalcin     ierr = PetscDTGaussTensorQuadrature(dim-1, 1, k+1, -1, +1, &fq);CHKERRQ(ierr);
1326066ea43fSLisandro Dalcin   }
1327066ea43fSLisandro Dalcin   /* Create finite element */
1328066ea43fSLisandro Dalcin   ierr = PetscFECreate(comm, fem);CHKERRQ(ierr);
1329066ea43fSLisandro Dalcin   ierr = PetscFESetType(*fem, PETSCFEBASIC);CHKERRQ(ierr);
1330066ea43fSLisandro Dalcin   ierr = PetscFESetNumComponents(*fem, Nc);CHKERRQ(ierr);
1331066ea43fSLisandro Dalcin   ierr = PetscFESetBasisSpace(*fem, P);CHKERRQ(ierr);
1332066ea43fSLisandro Dalcin   ierr = PetscFESetDualSpace(*fem, Q);CHKERRQ(ierr);
1333066ea43fSLisandro Dalcin   ierr = PetscFESetQuadrature(*fem, q);CHKERRQ(ierr);
1334066ea43fSLisandro Dalcin   ierr = PetscFESetFaceQuadrature(*fem, fq);CHKERRQ(ierr);
1335066ea43fSLisandro Dalcin   if (prefix) {
1336066ea43fSLisandro Dalcin     ierr = PetscObjectSetOptionsPrefix((PetscObject) *fem, prefix);CHKERRQ(ierr);
1337066ea43fSLisandro Dalcin     ierr = PetscFESetFromOptions(*fem);CHKERRQ(ierr);
1338066ea43fSLisandro Dalcin     ierr = PetscObjectSetOptionsPrefix((PetscObject) *fem, NULL);CHKERRQ(ierr);
1339066ea43fSLisandro Dalcin   }
1340066ea43fSLisandro Dalcin   ierr = PetscFESetUp(*fem);CHKERRQ(ierr);
1341066ea43fSLisandro Dalcin   /* Cleanup */
1342066ea43fSLisandro Dalcin   ierr = PetscSpaceDestroy(&P);CHKERRQ(ierr);
1343066ea43fSLisandro Dalcin   ierr = PetscDualSpaceDestroy(&Q);CHKERRQ(ierr);
1344066ea43fSLisandro Dalcin   ierr = PetscQuadratureDestroy(&q);CHKERRQ(ierr);
1345066ea43fSLisandro Dalcin   ierr = PetscQuadratureDestroy(&fq);CHKERRQ(ierr);
1346066ea43fSLisandro Dalcin   /* Set finite element name */
1347066ea43fSLisandro Dalcin   ierr = PetscSNPrintf(name, sizeof(name), "%s%D", isSimplex? "P" : "Q", k);CHKERRQ(ierr);
1348066ea43fSLisandro Dalcin   ierr = PetscFESetName(*fem, name);CHKERRQ(ierr);
1349066ea43fSLisandro Dalcin   PetscFunctionReturn(0);
135096ca5757SLisandro Dalcin }
135196ca5757SLisandro Dalcin 
1352d6689ca9SLisandro Dalcin /*@C
1353d6689ca9SLisandro Dalcin   DMPlexCreateGmshFromFile - Create a DMPlex mesh from a Gmsh file
1354d6689ca9SLisandro Dalcin 
1355d6689ca9SLisandro Dalcin + comm        - The MPI communicator
1356d6689ca9SLisandro Dalcin . filename    - Name of the Gmsh file
1357d6689ca9SLisandro Dalcin - interpolate - Create faces and edges in the mesh
1358d6689ca9SLisandro Dalcin 
1359d6689ca9SLisandro Dalcin   Output Parameter:
1360d6689ca9SLisandro Dalcin . dm  - The DM object representing the mesh
1361d6689ca9SLisandro Dalcin 
1362d6689ca9SLisandro Dalcin   Level: beginner
1363d6689ca9SLisandro Dalcin 
1364d6689ca9SLisandro Dalcin .seealso: DMPlexCreateFromFile(), DMPlexCreateGmsh(), DMPlexCreate()
1365d6689ca9SLisandro Dalcin @*/
1366d6689ca9SLisandro Dalcin PetscErrorCode DMPlexCreateGmshFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm)
1367d6689ca9SLisandro Dalcin {
1368d6689ca9SLisandro Dalcin   PetscViewer     viewer;
1369d6689ca9SLisandro Dalcin   PetscMPIInt     rank;
1370d6689ca9SLisandro Dalcin   int             fileType;
1371d6689ca9SLisandro Dalcin   PetscViewerType vtype;
1372d6689ca9SLisandro Dalcin   PetscErrorCode  ierr;
1373d6689ca9SLisandro Dalcin 
1374d6689ca9SLisandro Dalcin   PetscFunctionBegin;
1375ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
1376d6689ca9SLisandro Dalcin 
1377d6689ca9SLisandro Dalcin   /* Determine Gmsh file type (ASCII or binary) from file header */
1378*dd400576SPatrick Sanan   if (rank == 0) {
13790598e1a2SLisandro Dalcin     GmshFile    gmsh[1];
1380d6689ca9SLisandro Dalcin     char        line[PETSC_MAX_PATH_LEN];
1381d6689ca9SLisandro Dalcin     int         snum;
1382d6689ca9SLisandro Dalcin     float       version;
1383d6689ca9SLisandro Dalcin 
1384580bdb30SBarry Smith     ierr = PetscArrayzero(gmsh,1);CHKERRQ(ierr);
1385d6689ca9SLisandro Dalcin     ierr = PetscViewerCreate(PETSC_COMM_SELF, &gmsh->viewer);CHKERRQ(ierr);
1386d6689ca9SLisandro Dalcin     ierr = PetscViewerSetType(gmsh->viewer, PETSCVIEWERASCII);CHKERRQ(ierr);
1387d6689ca9SLisandro Dalcin     ierr = PetscViewerFileSetMode(gmsh->viewer, FILE_MODE_READ);CHKERRQ(ierr);
1388d6689ca9SLisandro Dalcin     ierr = PetscViewerFileSetName(gmsh->viewer, filename);CHKERRQ(ierr);
1389d6689ca9SLisandro Dalcin     /* Read only the first two lines of the Gmsh file */
1390d6689ca9SLisandro Dalcin     ierr = GmshReadSection(gmsh, line);CHKERRQ(ierr);
1391d6689ca9SLisandro Dalcin     ierr = GmshExpect(gmsh, "$MeshFormat", line);CHKERRQ(ierr);
1392d6689ca9SLisandro Dalcin     ierr = GmshReadString(gmsh, line, 2);CHKERRQ(ierr);
1393d6689ca9SLisandro Dalcin     snum = sscanf(line, "%f %d", &version, &fileType);
13940598e1a2SLisandro Dalcin     if (snum != 2) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line);
13950598e1a2SLisandro Dalcin     if (version < 2.2) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at least 2.2", (double)version);
13960598e1a2SLisandro Dalcin     if ((int)version == 3) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f not supported", (double)version);
13970598e1a2SLisandro Dalcin     if (version > 4.1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at most 4.1", (double)version);
1398d6689ca9SLisandro Dalcin     ierr = PetscViewerDestroy(&gmsh->viewer);CHKERRQ(ierr);
1399d6689ca9SLisandro Dalcin   }
1400ffc4695bSBarry Smith   ierr = MPI_Bcast(&fileType, 1, MPI_INT, 0, comm);CHKERRMPI(ierr);
1401d6689ca9SLisandro Dalcin   vtype = (fileType == 0) ? PETSCVIEWERASCII : PETSCVIEWERBINARY;
1402d6689ca9SLisandro Dalcin 
1403d6689ca9SLisandro Dalcin   /* Create appropriate viewer and build plex */
1404d6689ca9SLisandro Dalcin   ierr = PetscViewerCreate(comm, &viewer);CHKERRQ(ierr);
1405d6689ca9SLisandro Dalcin   ierr = PetscViewerSetType(viewer, vtype);CHKERRQ(ierr);
1406d6689ca9SLisandro Dalcin   ierr = PetscViewerFileSetMode(viewer, FILE_MODE_READ);CHKERRQ(ierr);
1407d6689ca9SLisandro Dalcin   ierr = PetscViewerFileSetName(viewer, filename);CHKERRQ(ierr);
1408d6689ca9SLisandro Dalcin   ierr = DMPlexCreateGmsh(comm, viewer, interpolate, dm);CHKERRQ(ierr);
1409d6689ca9SLisandro Dalcin   ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1410d6689ca9SLisandro Dalcin   PetscFunctionReturn(0);
1411d6689ca9SLisandro Dalcin }
1412d6689ca9SLisandro Dalcin 
1413331830f3SMatthew G. Knepley /*@
14147d282ae0SMichael Lange   DMPlexCreateGmsh - Create a DMPlex mesh from a Gmsh file viewer
1415331830f3SMatthew G. Knepley 
1416d083f849SBarry Smith   Collective
1417331830f3SMatthew G. Knepley 
1418331830f3SMatthew G. Knepley   Input Parameters:
1419331830f3SMatthew G. Knepley + comm  - The MPI communicator
1420331830f3SMatthew G. Knepley . viewer - The Viewer associated with a Gmsh file
1421331830f3SMatthew G. Knepley - interpolate - Create faces and edges in the mesh
1422331830f3SMatthew G. Knepley 
1423331830f3SMatthew G. Knepley   Output Parameter:
1424331830f3SMatthew G. Knepley . dm  - The DM object representing the mesh
1425331830f3SMatthew G. Knepley 
1426698a79b9SLisandro Dalcin   Note: http://gmsh.info/doc/texinfo/gmsh.html#MSH-file-format
1427331830f3SMatthew G. Knepley 
1428331830f3SMatthew G. Knepley   Level: beginner
1429331830f3SMatthew G. Knepley 
1430331830f3SMatthew G. Knepley .seealso: DMPLEX, DMCreate()
1431331830f3SMatthew G. Knepley @*/
1432331830f3SMatthew G. Knepley PetscErrorCode DMPlexCreateGmsh(MPI_Comm comm, PetscViewer viewer, PetscBool interpolate, DM *dm)
1433331830f3SMatthew G. Knepley {
14340598e1a2SLisandro Dalcin   GmshMesh      *mesh = NULL;
143511c56cb0SLisandro Dalcin   PetscViewer    parentviewer = NULL;
14360598e1a2SLisandro Dalcin   PetscBT        periodicVerts = NULL;
14370598e1a2SLisandro Dalcin   PetscBT        periodicCells = NULL;
1438066ea43fSLisandro Dalcin   DM             cdm;
1439331830f3SMatthew G. Knepley   PetscSection   coordSection;
1440331830f3SMatthew G. Knepley   Vec            coordinates;
14417dd454faSLisandro Dalcin   DMLabel        cellSets = NULL, faceSets = NULL, vertSets = NULL, marker = NULL;
1442066ea43fSLisandro Dalcin   PetscInt       dim = 0, coordDim = -1, order = 0;
14430598e1a2SLisandro Dalcin   PetscInt       numNodes = 0, numElems = 0, numVerts = 0, numCells = 0;
1444066ea43fSLisandro Dalcin   PetscInt       cell, cone[8], e, n, v, d;
14450598e1a2SLisandro Dalcin   PetscBool      binary, usemarker = PETSC_FALSE;
14460598e1a2SLisandro Dalcin   PetscBool      hybrid = interpolate, periodic = PETSC_TRUE;
1447066ea43fSLisandro Dalcin   PetscBool      highOrder = PETSC_TRUE, highOrderSet, project = PETSC_FALSE;
1448066ea43fSLisandro Dalcin   PetscBool      isSimplex = PETSC_FALSE, isHybrid = PETSC_FALSE, hasTetra = PETSC_FALSE;
14490598e1a2SLisandro Dalcin   PetscMPIInt    rank;
1450331830f3SMatthew G. Knepley   PetscErrorCode ierr;
1451331830f3SMatthew G. Knepley 
1452331830f3SMatthew G. Knepley   PetscFunctionBegin;
1453ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
1454ef12879bSLisandro Dalcin   ierr = PetscObjectOptionsBegin((PetscObject)viewer);CHKERRQ(ierr);
1455ef12879bSLisandro Dalcin   ierr = PetscOptionsHead(PetscOptionsObject,"DMPlex Gmsh options");CHKERRQ(ierr);
14560598e1a2SLisandro Dalcin   ierr = PetscOptionsBool("-dm_plex_gmsh_hybrid", "Generate hybrid cell bounds", "DMPlexCreateGmsh", hybrid, &hybrid, NULL);CHKERRQ(ierr);
1457ef12879bSLisandro Dalcin   ierr = PetscOptionsBool("-dm_plex_gmsh_periodic","Read Gmsh periodic section", "DMPlexCreateGmsh", periodic, &periodic, NULL);CHKERRQ(ierr);
1458066ea43fSLisandro Dalcin   ierr = PetscOptionsBool("-dm_plex_gmsh_highorder","Generate high-order coordinates", "DMPlexCreateGmsh", highOrder, &highOrder, &highOrderSet);CHKERRQ(ierr);
1459066ea43fSLisandro Dalcin   ierr = PetscOptionsBool("-dm_plex_gmsh_project", "Project high-order coordinates to a different space", "DMPlexCreateGmsh", project, &project, NULL);CHKERRQ(ierr);
1460ef12879bSLisandro Dalcin   ierr = PetscOptionsBool("-dm_plex_gmsh_use_marker", "Generate marker label", "DMPlexCreateGmsh", usemarker, &usemarker, NULL);CHKERRQ(ierr);
14610598e1a2SLisandro Dalcin   ierr = PetscOptionsBoundedInt("-dm_plex_gmsh_spacedim", "Embedding space dimension", "DMPlexCreateGmsh", coordDim, &coordDim, NULL, PETSC_DECIDE);CHKERRQ(ierr);
1462ef12879bSLisandro Dalcin   ierr = PetscOptionsTail();CHKERRQ(ierr);
1463ef12879bSLisandro Dalcin   ierr = PetscOptionsEnd();CHKERRQ(ierr);
14640598e1a2SLisandro Dalcin 
14650598e1a2SLisandro Dalcin   ierr = GmshCellInfoSetUp();CHKERRQ(ierr);
146611c56cb0SLisandro Dalcin 
1467331830f3SMatthew G. Knepley   ierr = DMCreate(comm, dm);CHKERRQ(ierr);
1468331830f3SMatthew G. Knepley   ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr);
14690598e1a2SLisandro Dalcin   ierr = PetscLogEventBegin(DMPLEX_CreateGmsh,*dm,NULL,NULL,NULL);CHKERRQ(ierr);
147011c56cb0SLisandro Dalcin 
147111c56cb0SLisandro Dalcin   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &binary);CHKERRQ(ierr);
147211c56cb0SLisandro Dalcin 
147311c56cb0SLisandro Dalcin   /* Binary viewers read on all ranks, get subviewer to read only in rank 0 */
14743b46f529SLisandro Dalcin   if (binary) {
147511c56cb0SLisandro Dalcin     parentviewer = viewer;
147611c56cb0SLisandro Dalcin     ierr = PetscViewerGetSubViewer(parentviewer, PETSC_COMM_SELF, &viewer);CHKERRQ(ierr);
147711c56cb0SLisandro Dalcin   }
147811c56cb0SLisandro Dalcin 
1479*dd400576SPatrick Sanan   if (rank == 0) {
14800598e1a2SLisandro Dalcin     GmshFile  gmsh[1];
1481698a79b9SLisandro Dalcin     char      line[PETSC_MAX_PATH_LEN];
1482698a79b9SLisandro Dalcin     PetscBool match;
1483331830f3SMatthew G. Knepley 
1484580bdb30SBarry Smith     ierr = PetscArrayzero(gmsh,1);CHKERRQ(ierr);
1485698a79b9SLisandro Dalcin     gmsh->viewer = viewer;
1486698a79b9SLisandro Dalcin     gmsh->binary = binary;
1487698a79b9SLisandro Dalcin 
14880598e1a2SLisandro Dalcin     ierr = GmshMeshCreate(&mesh);CHKERRQ(ierr);
14890598e1a2SLisandro Dalcin 
1490698a79b9SLisandro Dalcin     /* Read mesh format */
1491d6689ca9SLisandro Dalcin     ierr = GmshReadSection(gmsh, line);CHKERRQ(ierr);
1492d6689ca9SLisandro Dalcin     ierr = GmshExpect(gmsh, "$MeshFormat", line);CHKERRQ(ierr);
14930598e1a2SLisandro Dalcin     ierr = GmshReadMeshFormat(gmsh);CHKERRQ(ierr);
1494d6689ca9SLisandro Dalcin     ierr = GmshReadEndSection(gmsh, "$EndMeshFormat", line);CHKERRQ(ierr);
149511c56cb0SLisandro Dalcin 
1496dc0ede3bSMatthew G. Knepley     /* OPTIONAL Read physical names */
1497d6689ca9SLisandro Dalcin     ierr = GmshReadSection(gmsh, line);CHKERRQ(ierr);
1498d6689ca9SLisandro Dalcin     ierr = GmshMatch(gmsh, "$PhysicalNames", line, &match);CHKERRQ(ierr);
1499dc0ede3bSMatthew G. Knepley     if (match) {
15000598e1a2SLisandro Dalcin       ierr = GmshExpect(gmsh, "$PhysicalNames", line);CHKERRQ(ierr);
15010598e1a2SLisandro Dalcin       ierr = GmshReadPhysicalNames(gmsh);CHKERRQ(ierr);
1502d6689ca9SLisandro Dalcin       ierr = GmshReadEndSection(gmsh, "$EndPhysicalNames", line);CHKERRQ(ierr);
1503698a79b9SLisandro Dalcin       /* Initial read for entity section */
1504d6689ca9SLisandro Dalcin       ierr = GmshReadSection(gmsh, line);CHKERRQ(ierr);
1505dc0ede3bSMatthew G. Knepley     }
150611c56cb0SLisandro Dalcin 
1507de78e4feSLisandro Dalcin     /* Read entities */
1508698a79b9SLisandro Dalcin     if (gmsh->fileFormat >= 40) {
1509d6689ca9SLisandro Dalcin       ierr = GmshExpect(gmsh, "$Entities", line);CHKERRQ(ierr);
15100598e1a2SLisandro Dalcin       ierr = GmshReadEntities(gmsh, mesh);CHKERRQ(ierr);
1511d6689ca9SLisandro Dalcin       ierr = GmshReadEndSection(gmsh, "$EndEntities", line);CHKERRQ(ierr);
1512698a79b9SLisandro Dalcin       /* Initial read for nodes section */
1513d6689ca9SLisandro Dalcin       ierr = GmshReadSection(gmsh, line);CHKERRQ(ierr);
1514de78e4feSLisandro Dalcin     }
1515de78e4feSLisandro Dalcin 
1516698a79b9SLisandro Dalcin     /* Read nodes */
1517d6689ca9SLisandro Dalcin     ierr = GmshExpect(gmsh, "$Nodes", line);CHKERRQ(ierr);
15180598e1a2SLisandro Dalcin     ierr = GmshReadNodes(gmsh, mesh);CHKERRQ(ierr);
1519d6689ca9SLisandro Dalcin     ierr = GmshReadEndSection(gmsh, "$EndNodes", line);CHKERRQ(ierr);
152011c56cb0SLisandro Dalcin 
1521698a79b9SLisandro Dalcin     /* Read elements */
1522feb237baSPierre Jolivet     ierr = GmshReadSection(gmsh, line);CHKERRQ(ierr);
1523d6689ca9SLisandro Dalcin     ierr = GmshExpect(gmsh, "$Elements", line);CHKERRQ(ierr);
15240598e1a2SLisandro Dalcin     ierr = GmshReadElements(gmsh, mesh);CHKERRQ(ierr);
1525d6689ca9SLisandro Dalcin     ierr = GmshReadEndSection(gmsh, "$EndElements", line);CHKERRQ(ierr);
1526de78e4feSLisandro Dalcin 
15270598e1a2SLisandro Dalcin     /* Read periodic section (OPTIONAL) */
1528698a79b9SLisandro Dalcin     if (periodic) {
1529ef12879bSLisandro Dalcin       ierr = GmshReadSection(gmsh, line);CHKERRQ(ierr);
1530ef12879bSLisandro Dalcin       ierr = GmshMatch(gmsh, "$Periodic", line, &periodic);CHKERRQ(ierr);
1531ef12879bSLisandro Dalcin     }
1532ef12879bSLisandro Dalcin     if (periodic) {
1533d6689ca9SLisandro Dalcin       ierr = GmshExpect(gmsh, "$Periodic", line);CHKERRQ(ierr);
15340598e1a2SLisandro Dalcin       ierr = GmshReadPeriodic(gmsh, mesh);CHKERRQ(ierr);
1535d6689ca9SLisandro Dalcin       ierr = GmshReadEndSection(gmsh, "$EndPeriodic", line);CHKERRQ(ierr);
1536698a79b9SLisandro Dalcin     }
1537698a79b9SLisandro Dalcin 
1538698a79b9SLisandro Dalcin     ierr = PetscFree(gmsh->wbuf);CHKERRQ(ierr);
1539698a79b9SLisandro Dalcin     ierr = PetscFree(gmsh->sbuf);CHKERRQ(ierr);
15400598e1a2SLisandro Dalcin     ierr = PetscFree(gmsh->nbuf);CHKERRQ(ierr);
15410598e1a2SLisandro Dalcin 
15420598e1a2SLisandro Dalcin     dim       = mesh->dim;
1543066ea43fSLisandro Dalcin     order     = mesh->order;
15440598e1a2SLisandro Dalcin     numNodes  = mesh->numNodes;
15450598e1a2SLisandro Dalcin     numElems  = mesh->numElems;
15460598e1a2SLisandro Dalcin     numVerts  = mesh->numVerts;
15470598e1a2SLisandro Dalcin     numCells  = mesh->numCells;
1548066ea43fSLisandro Dalcin 
1549066ea43fSLisandro Dalcin     {
1550066ea43fSLisandro Dalcin       GmshElement *elemA = mesh->numCells > 0 ? mesh->elements : NULL;
1551066ea43fSLisandro Dalcin       GmshElement *elemB = elemA ? elemA + mesh->numCells - 1  : NULL;
1552066ea43fSLisandro Dalcin       int ptA = elemA ? GmshCellMap[elemA->cellType].polytope : -1;
1553066ea43fSLisandro Dalcin       int ptB = elemB ? GmshCellMap[elemB->cellType].polytope : -1;
1554066ea43fSLisandro Dalcin       isSimplex = (ptA == GMSH_QUA || ptA == GMSH_HEX) ? PETSC_FALSE : PETSC_TRUE;
1555066ea43fSLisandro Dalcin       isHybrid  = (ptA == ptB) ? PETSC_FALSE : PETSC_TRUE;
1556066ea43fSLisandro Dalcin       hasTetra  = (ptA == GMSH_TET) ? PETSC_TRUE : PETSC_FALSE;
1557066ea43fSLisandro Dalcin     }
1558698a79b9SLisandro Dalcin   }
1559698a79b9SLisandro Dalcin 
1560698a79b9SLisandro Dalcin   if (parentviewer) {
1561698a79b9SLisandro Dalcin     ierr = PetscViewerRestoreSubViewer(parentviewer, PETSC_COMM_SELF, &viewer);CHKERRQ(ierr);
1562698a79b9SLisandro Dalcin   }
1563698a79b9SLisandro Dalcin 
1564066ea43fSLisandro Dalcin   {
1565066ea43fSLisandro Dalcin     int buf[6];
1566698a79b9SLisandro Dalcin 
1567066ea43fSLisandro Dalcin     buf[0] = (int)dim;
1568066ea43fSLisandro Dalcin     buf[1] = (int)order;
1569066ea43fSLisandro Dalcin     buf[2] = periodic;
1570066ea43fSLisandro Dalcin     buf[3] = isSimplex;
1571066ea43fSLisandro Dalcin     buf[4] = isHybrid;
1572066ea43fSLisandro Dalcin     buf[5] = hasTetra;
1573066ea43fSLisandro Dalcin 
1574ffc4695bSBarry Smith     ierr = MPI_Bcast(buf, 6, MPI_INT, 0, comm);CHKERRMPI(ierr);
1575066ea43fSLisandro Dalcin 
1576066ea43fSLisandro Dalcin     dim       = buf[0];
1577066ea43fSLisandro Dalcin     order     = buf[1];
1578066ea43fSLisandro Dalcin     periodic  = buf[2] ? PETSC_TRUE : PETSC_FALSE;
1579066ea43fSLisandro Dalcin     isSimplex = buf[3] ? PETSC_TRUE : PETSC_FALSE;
1580066ea43fSLisandro Dalcin     isHybrid  = buf[4] ? PETSC_TRUE : PETSC_FALSE;
1581066ea43fSLisandro Dalcin     hasTetra  = buf[5] ? PETSC_TRUE : PETSC_FALSE;
1582dea2a3c7SStefano Zampini   }
1583dea2a3c7SStefano Zampini 
1584066ea43fSLisandro Dalcin   if (!highOrderSet) highOrder = (order > 1) ? PETSC_TRUE : PETSC_FALSE;
1585066ea43fSLisandro Dalcin   if (highOrder && isHybrid) SETERRQ(comm, PETSC_ERR_SUP, "No support for discretization on hybrid meshes yet");
1586066ea43fSLisandro Dalcin 
15870598e1a2SLisandro Dalcin   /* We do not want this label automatically computed, instead we fill it here */
15880598e1a2SLisandro Dalcin   ierr = DMCreateLabel(*dm, "celltype");CHKERRQ(ierr);
158911c56cb0SLisandro Dalcin 
1590a4bb7517SMichael Lange   /* Allocate the cell-vertex mesh */
15910598e1a2SLisandro Dalcin   ierr = DMPlexSetChart(*dm, 0, numCells+numVerts);CHKERRQ(ierr);
15920598e1a2SLisandro Dalcin   for (cell = 0; cell < numCells; ++cell) {
15930598e1a2SLisandro Dalcin     GmshElement *elem = mesh->elements + cell;
15940598e1a2SLisandro Dalcin     DMPolytopeType ctype = DMPolytopeTypeFromGmsh(elem->cellType);
15950598e1a2SLisandro Dalcin     if (hybrid && hasTetra && ctype == DM_POLYTOPE_TRI_PRISM) ctype = DM_POLYTOPE_TRI_PRISM_TENSOR;
15960598e1a2SLisandro Dalcin     ierr = DMPlexSetConeSize(*dm, cell, elem->numVerts);CHKERRQ(ierr);
15970598e1a2SLisandro Dalcin     ierr = DMPlexSetCellType(*dm, cell, ctype);CHKERRQ(ierr);
1598db397164SMichael Lange   }
15990598e1a2SLisandro Dalcin   for (v = numCells; v < numCells+numVerts; ++v) {
160096ca5757SLisandro Dalcin     ierr = DMPlexSetCellType(*dm, v, DM_POLYTOPE_POINT);CHKERRQ(ierr);
160196ca5757SLisandro Dalcin   }
1602331830f3SMatthew G. Knepley   ierr = DMSetUp(*dm);CHKERRQ(ierr);
160396ca5757SLisandro Dalcin 
1604a4bb7517SMichael Lange   /* Add cell-vertex connections */
16050598e1a2SLisandro Dalcin   for (cell = 0; cell < numCells; ++cell) {
16060598e1a2SLisandro Dalcin     GmshElement *elem = mesh->elements + cell;
16070598e1a2SLisandro Dalcin     for (v = 0; v < elem->numVerts; ++v) {
16080598e1a2SLisandro Dalcin       const PetscInt nn = elem->nodes[v];
16090598e1a2SLisandro Dalcin       const PetscInt vv = mesh->vertexMap[nn];
16100598e1a2SLisandro Dalcin       cone[v] = numCells + vv;
1611db397164SMichael Lange     }
16120598e1a2SLisandro Dalcin     ierr = DMPlexReorderCell(*dm, cell, cone);CHKERRQ(ierr);
16130598e1a2SLisandro Dalcin     ierr = DMPlexSetCone(*dm, cell, cone);CHKERRQ(ierr);
1614a4bb7517SMichael Lange   }
161596ca5757SLisandro Dalcin 
1616c73cfb54SMatthew G. Knepley   ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr);
1617331830f3SMatthew G. Knepley   ierr = DMPlexSymmetrize(*dm);CHKERRQ(ierr);
1618331830f3SMatthew G. Knepley   ierr = DMPlexStratify(*dm);CHKERRQ(ierr);
1619331830f3SMatthew G. Knepley   if (interpolate) {
16205fd9971aSMatthew G. Knepley     DM idm;
1621331830f3SMatthew G. Knepley 
1622331830f3SMatthew G. Knepley     ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr);
1623331830f3SMatthew G. Knepley     ierr = DMDestroy(dm);CHKERRQ(ierr);
1624331830f3SMatthew G. Knepley     *dm  = idm;
1625331830f3SMatthew G. Knepley   }
1626917266a4SLisandro Dalcin 
1627f6c8a31fSLisandro Dalcin   if (usemarker && !interpolate && dim > 1) SETERRQ(comm,PETSC_ERR_SUP,"Cannot create marker label without interpolation");
1628*dd400576SPatrick Sanan   if (rank == 0 && usemarker) {
1629d3f73514SStefano Zampini     PetscInt f, fStart, fEnd;
1630d3f73514SStefano Zampini 
1631d3f73514SStefano Zampini     ierr = DMCreateLabel(*dm, "marker");CHKERRQ(ierr);
1632d3f73514SStefano Zampini     ierr = DMPlexGetHeightStratum(*dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
1633d3f73514SStefano Zampini     for (f = fStart; f < fEnd; ++f) {
1634d3f73514SStefano Zampini       PetscInt suppSize;
1635d3f73514SStefano Zampini 
1636d3f73514SStefano Zampini       ierr = DMPlexGetSupportSize(*dm, f, &suppSize);CHKERRQ(ierr);
1637d3f73514SStefano Zampini       if (suppSize == 1) {
1638d3f73514SStefano Zampini         PetscInt *cone = NULL, coneSize, p;
1639d3f73514SStefano Zampini 
1640d3f73514SStefano Zampini         ierr = DMPlexGetTransitiveClosure(*dm, f, PETSC_TRUE, &coneSize, &cone);CHKERRQ(ierr);
1641d3f73514SStefano Zampini         for (p = 0; p < coneSize; p += 2) {
16427dd454faSLisandro Dalcin           ierr = DMSetLabelValue_Fast(*dm, &marker, "marker", cone[p], 1);CHKERRQ(ierr);
1643d3f73514SStefano Zampini         }
1644d3f73514SStefano Zampini         ierr = DMPlexRestoreTransitiveClosure(*dm, f, PETSC_TRUE, &coneSize, &cone);CHKERRQ(ierr);
1645d3f73514SStefano Zampini       }
1646d3f73514SStefano Zampini     }
1647d3f73514SStefano Zampini   }
164816ad7e67SMichael Lange 
1649*dd400576SPatrick Sanan   if (rank == 0) {
165011c56cb0SLisandro Dalcin     PetscInt vStart, vEnd;
1651d1a54cefSMatthew G. Knepley 
165216ad7e67SMichael Lange     ierr = DMPlexGetDepthStratum(*dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
16530598e1a2SLisandro Dalcin     for (cell = 0, e = 0; e < numElems; ++e) {
16540598e1a2SLisandro Dalcin       GmshElement *elem = mesh->elements + e;
16556e1dd89aSLawrence Mitchell 
16566e1dd89aSLawrence Mitchell       /* Create cell sets */
16570598e1a2SLisandro Dalcin       if (elem->dim == dim && dim > 0) {
16580598e1a2SLisandro Dalcin         if (elem->numTags > 0) {
16597dd454faSLisandro Dalcin           ierr = DMSetLabelValue_Fast(*dm, &cellSets, "Cell Sets", cell, elem->tags[0]);CHKERRQ(ierr);
16606e1dd89aSLawrence Mitchell         }
1661917266a4SLisandro Dalcin         cell++;
16626e1dd89aSLawrence Mitchell       }
16630c070f12SSander Arens 
16640598e1a2SLisandro Dalcin       /* Create face sets */
16650598e1a2SLisandro Dalcin       if (interpolate && elem->dim == dim-1) {
16660598e1a2SLisandro Dalcin         PetscInt        joinSize;
16670598e1a2SLisandro Dalcin         const PetscInt *join = NULL;
16680598e1a2SLisandro Dalcin         /* Find the relevant facet with vertex joins */
16690598e1a2SLisandro Dalcin         for (v = 0; v < elem->numVerts; ++v) {
16700598e1a2SLisandro Dalcin           const PetscInt nn = elem->nodes[v];
16710598e1a2SLisandro Dalcin           const PetscInt vv = mesh->vertexMap[nn];
16720598e1a2SLisandro Dalcin           cone[v] = vStart + vv;
16730598e1a2SLisandro Dalcin         }
16740598e1a2SLisandro Dalcin         ierr = DMPlexGetFullJoin(*dm, elem->numVerts, cone, &joinSize, &join);CHKERRQ(ierr);
16750598e1a2SLisandro Dalcin         if (joinSize != 1) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_SUP, "Could not determine Plex facet for Gmsh element %D (Plex cell %D)", elem->id, e);
16767dd454faSLisandro Dalcin         ierr = DMSetLabelValue_Fast(*dm, &faceSets, "Face Sets", join[0], elem->tags[0]);CHKERRQ(ierr);
16770598e1a2SLisandro Dalcin         ierr = DMPlexRestoreJoin(*dm, elem->numVerts, cone, &joinSize, &join);CHKERRQ(ierr);
16780598e1a2SLisandro Dalcin       }
16790598e1a2SLisandro Dalcin 
16800c070f12SSander Arens       /* Create vertex sets */
16810598e1a2SLisandro Dalcin       if (elem->dim == 0) {
16820598e1a2SLisandro Dalcin         if (elem->numTags > 0) {
16830598e1a2SLisandro Dalcin           const PetscInt nn = elem->nodes[0];
16840598e1a2SLisandro Dalcin           const PetscInt vv = mesh->vertexMap[nn];
16857dd454faSLisandro Dalcin           ierr = DMSetLabelValue_Fast(*dm, &vertSets, "Vertex Sets", vStart + vv, elem->tags[0]);CHKERRQ(ierr);
16860598e1a2SLisandro Dalcin         }
16870598e1a2SLisandro Dalcin       }
16880598e1a2SLisandro Dalcin     }
16890598e1a2SLisandro Dalcin   }
16900598e1a2SLisandro Dalcin 
16917dd454faSLisandro Dalcin   { /* Create Cell/Face/Vertex Sets labels at all processes */
16927dd454faSLisandro Dalcin     enum {n = 4};
16937dd454faSLisandro Dalcin     PetscBool flag[n];
16947dd454faSLisandro Dalcin 
16957dd454faSLisandro Dalcin     flag[0] = cellSets ? PETSC_TRUE : PETSC_FALSE;
16967dd454faSLisandro Dalcin     flag[1] = faceSets ? PETSC_TRUE : PETSC_FALSE;
16977dd454faSLisandro Dalcin     flag[2] = vertSets ? PETSC_TRUE : PETSC_FALSE;
16987dd454faSLisandro Dalcin     flag[3] = marker   ? PETSC_TRUE : PETSC_FALSE;
16997dd454faSLisandro Dalcin     ierr = MPI_Bcast(flag, n, MPIU_BOOL, 0, comm);CHKERRMPI(ierr);
17007dd454faSLisandro Dalcin     if (flag[0]) {ierr = DMCreateLabel(*dm, "Cell Sets");CHKERRQ(ierr);}
17017dd454faSLisandro Dalcin     if (flag[1]) {ierr = DMCreateLabel(*dm, "Face Sets");CHKERRQ(ierr);}
17027dd454faSLisandro Dalcin     if (flag[2]) {ierr = DMCreateLabel(*dm, "Vertex Sets");CHKERRQ(ierr);}
17037dd454faSLisandro Dalcin     if (flag[3]) {ierr = DMCreateLabel(*dm, "marker");CHKERRQ(ierr);}
17047dd454faSLisandro Dalcin   }
17057dd454faSLisandro Dalcin 
17060598e1a2SLisandro Dalcin   if (periodic) {
17070598e1a2SLisandro Dalcin     ierr = PetscBTCreate(numVerts, &periodicVerts);CHKERRQ(ierr);
17080598e1a2SLisandro Dalcin     for (n = 0; n < numNodes; ++n) {
17090598e1a2SLisandro Dalcin       if (mesh->vertexMap[n] >= 0) {
17100598e1a2SLisandro Dalcin         if (PetscUnlikely(mesh->periodMap[n] != n)) {
17110598e1a2SLisandro Dalcin           PetscInt m = mesh->periodMap[n];
17120598e1a2SLisandro Dalcin           ierr = PetscBTSet(periodicVerts, mesh->vertexMap[n]);CHKERRQ(ierr);
17130598e1a2SLisandro Dalcin           ierr = PetscBTSet(periodicVerts, mesh->vertexMap[m]);CHKERRQ(ierr);
17140598e1a2SLisandro Dalcin         }
17150598e1a2SLisandro Dalcin       }
17160598e1a2SLisandro Dalcin     }
17170598e1a2SLisandro Dalcin     ierr = PetscBTCreate(numCells, &periodicCells);CHKERRQ(ierr);
17180598e1a2SLisandro Dalcin     for (cell = 0; cell < numCells; ++cell) {
17190598e1a2SLisandro Dalcin       GmshElement *elem = mesh->elements + cell;
17200598e1a2SLisandro Dalcin       for (v = 0; v < elem->numVerts; ++v) {
17210598e1a2SLisandro Dalcin         PetscInt nn = elem->nodes[v];
17220598e1a2SLisandro Dalcin         PetscInt vv = mesh->vertexMap[nn];
17230598e1a2SLisandro Dalcin         if (PetscUnlikely(PetscBTLookup(periodicVerts, vv))) {
17240598e1a2SLisandro Dalcin           ierr = PetscBTSet(periodicCells, cell);CHKERRQ(ierr); break;
17250c070f12SSander Arens         }
17260c070f12SSander Arens       }
17270c070f12SSander Arens     }
172816ad7e67SMichael Lange   }
172916ad7e67SMichael Lange 
1730066ea43fSLisandro Dalcin   /* Setup coordinate DM */
17310598e1a2SLisandro Dalcin   if (coordDim < 0) coordDim = dim;
17320598e1a2SLisandro Dalcin   ierr = DMSetCoordinateDim(*dm, coordDim);CHKERRQ(ierr);
1733066ea43fSLisandro Dalcin   ierr = DMGetCoordinateDM(*dm, &cdm);CHKERRQ(ierr);
1734066ea43fSLisandro Dalcin   if (highOrder) {
1735066ea43fSLisandro Dalcin     PetscFE         fe;
1736066ea43fSLisandro Dalcin     PetscBool       continuity = periodic ? PETSC_FALSE : PETSC_TRUE;
1737066ea43fSLisandro Dalcin     PetscDTNodeType nodeType   = PETSCDTNODES_EQUISPACED;
1738066ea43fSLisandro Dalcin 
1739066ea43fSLisandro Dalcin     if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */
1740066ea43fSLisandro Dalcin 
1741066ea43fSLisandro Dalcin     ierr = GmshCreateFE(comm, NULL, isSimplex, continuity, nodeType, dim, coordDim, order, &fe);CHKERRQ(ierr);
1742066ea43fSLisandro Dalcin     ierr = PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_fe_view");CHKERRQ(ierr);
1743066ea43fSLisandro Dalcin     ierr = DMSetField(cdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr);
1744066ea43fSLisandro Dalcin     ierr = PetscFEDestroy(&fe);CHKERRQ(ierr);
1745066ea43fSLisandro Dalcin     ierr = DMCreateDS(cdm);CHKERRQ(ierr);
1746066ea43fSLisandro Dalcin   }
1747066ea43fSLisandro Dalcin 
1748066ea43fSLisandro Dalcin   /* Create coordinates */
1749066ea43fSLisandro Dalcin   if (highOrder) {
1750066ea43fSLisandro Dalcin 
1751066ea43fSLisandro Dalcin     PetscInt     maxDof = GmshNumNodes_HEX(order)*coordDim;
1752066ea43fSLisandro Dalcin     double       *coords = mesh ? mesh->nodelist->xyz : NULL;
1753066ea43fSLisandro Dalcin     PetscSection section;
1754066ea43fSLisandro Dalcin     PetscScalar  *cellCoords;
1755066ea43fSLisandro Dalcin 
1756066ea43fSLisandro Dalcin     ierr = DMSetLocalSection(cdm, NULL);CHKERRQ(ierr);
1757066ea43fSLisandro Dalcin     ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr);
1758066ea43fSLisandro Dalcin     ierr = PetscSectionClone(coordSection, &section);CHKERRQ(ierr);
1759066ea43fSLisandro Dalcin     ierr = DMPlexSetClosurePermutationTensor(cdm, 0, section);CHKERRQ(ierr); /* XXX Implement DMPlexSetClosurePermutationLexicographic() */
1760066ea43fSLisandro Dalcin 
1761066ea43fSLisandro Dalcin     ierr = DMCreateLocalVector(cdm, &coordinates);CHKERRQ(ierr);
1762066ea43fSLisandro Dalcin     ierr = PetscMalloc1(maxDof, &cellCoords);CHKERRQ(ierr);
1763066ea43fSLisandro Dalcin     for (cell = 0; cell < numCells; ++cell) {
1764066ea43fSLisandro Dalcin       GmshElement *elem = mesh->elements + cell;
1765066ea43fSLisandro Dalcin       const int *lexorder = GmshCellMap[elem->cellType].lexorder();
1766066ea43fSLisandro Dalcin       for (n = 0; n < elem->numNodes; ++n) {
1767066ea43fSLisandro Dalcin         const PetscInt node = elem->nodes[lexorder[n]];
1768066ea43fSLisandro Dalcin         for (d = 0; d < coordDim; ++d)
1769066ea43fSLisandro Dalcin           cellCoords[n*coordDim+d] = (PetscReal) coords[node*3+d];
1770066ea43fSLisandro Dalcin       }
1771066ea43fSLisandro Dalcin       ierr = DMPlexVecSetClosure(cdm, section, coordinates, cell, cellCoords, INSERT_VALUES);CHKERRQ(ierr);
1772066ea43fSLisandro Dalcin     }
1773066ea43fSLisandro Dalcin     ierr = PetscSectionDestroy(&section);CHKERRQ(ierr);
1774066ea43fSLisandro Dalcin     ierr = PetscFree(cellCoords);CHKERRQ(ierr);
1775066ea43fSLisandro Dalcin 
1776066ea43fSLisandro Dalcin   } else {
1777066ea43fSLisandro Dalcin 
1778066ea43fSLisandro Dalcin     PetscInt    *nodeMap;
1779066ea43fSLisandro Dalcin     double      *coords = mesh ? mesh->nodelist->xyz : NULL;
1780066ea43fSLisandro Dalcin     PetscScalar *pointCoords;
1781066ea43fSLisandro Dalcin 
1782066ea43fSLisandro Dalcin     ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr);
1783331830f3SMatthew G. Knepley     ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr);
17840598e1a2SLisandro Dalcin     ierr = PetscSectionSetFieldComponents(coordSection, 0, coordDim);CHKERRQ(ierr);
17850598e1a2SLisandro Dalcin     if (periodic) { /* we need to localize coordinates on cells */
17860598e1a2SLisandro Dalcin       ierr = PetscSectionSetChart(coordSection, 0, numCells+numVerts);CHKERRQ(ierr);
1787f45c9589SStefano Zampini     } else {
17880598e1a2SLisandro Dalcin       ierr = PetscSectionSetChart(coordSection, numCells, numCells+numVerts);CHKERRQ(ierr);
1789f45c9589SStefano Zampini     }
17900598e1a2SLisandro Dalcin     if (periodic) {
17910598e1a2SLisandro Dalcin       for (cell = 0; cell < numCells; ++cell) {
17920598e1a2SLisandro Dalcin         if (PetscUnlikely(PetscBTLookup(periodicCells, cell))) {
17930598e1a2SLisandro Dalcin           GmshElement *elem = mesh->elements + cell;
17940598e1a2SLisandro Dalcin           PetscInt dof = elem->numVerts * coordDim;
17950598e1a2SLisandro Dalcin           ierr = PetscSectionSetDof(coordSection, cell, dof);CHKERRQ(ierr);
17960598e1a2SLisandro Dalcin           ierr = PetscSectionSetFieldDof(coordSection, cell, 0, dof);CHKERRQ(ierr);
1797f45c9589SStefano Zampini         }
1798f45c9589SStefano Zampini       }
1799f45c9589SStefano Zampini     }
18000598e1a2SLisandro Dalcin     for (v = numCells; v < numCells+numVerts; ++v) {
18010598e1a2SLisandro Dalcin       ierr = PetscSectionSetDof(coordSection, v, coordDim);CHKERRQ(ierr);
18020598e1a2SLisandro Dalcin       ierr = PetscSectionSetFieldDof(coordSection, v, 0, coordDim);CHKERRQ(ierr);
18030598e1a2SLisandro Dalcin     }
1804331830f3SMatthew G. Knepley     ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr);
1805066ea43fSLisandro Dalcin 
1806066ea43fSLisandro Dalcin     ierr = DMCreateLocalVector(cdm, &coordinates);CHKERRQ(ierr);
1807066ea43fSLisandro Dalcin     ierr = VecGetArray(coordinates, &pointCoords);CHKERRQ(ierr);
18080598e1a2SLisandro Dalcin     if (periodic) {
18090598e1a2SLisandro Dalcin       for (cell = 0; cell < numCells; ++cell) {
18100598e1a2SLisandro Dalcin         if (PetscUnlikely(PetscBTLookup(periodicCells, cell))) {
18110598e1a2SLisandro Dalcin           GmshElement *elem = mesh->elements + cell;
18120598e1a2SLisandro Dalcin           PetscInt off, node;
18130598e1a2SLisandro Dalcin           for (v = 0; v < elem->numVerts; ++v)
18140598e1a2SLisandro Dalcin             cone[v] = elem->nodes[v];
1815066ea43fSLisandro Dalcin           ierr = DMPlexReorderCell(cdm, cell, cone);CHKERRQ(ierr);
18160598e1a2SLisandro Dalcin           ierr = PetscSectionGetOffset(coordSection, cell, &off);CHKERRQ(ierr);
18170598e1a2SLisandro Dalcin           for (v = 0; v < elem->numVerts; ++v)
18180598e1a2SLisandro Dalcin             for (node = cone[v], d = 0; d < coordDim; ++d)
1819066ea43fSLisandro Dalcin               pointCoords[off++] = (PetscReal) coords[node*3+d];
1820331830f3SMatthew G. Knepley         }
1821331830f3SMatthew G. Knepley       }
1822331830f3SMatthew G. Knepley     }
1823066ea43fSLisandro Dalcin     ierr = PetscMalloc1(numVerts, &nodeMap);CHKERRQ(ierr);
18240598e1a2SLisandro Dalcin     for (n = 0; n < numNodes; n++)
18250598e1a2SLisandro Dalcin       if (mesh->vertexMap[n] >= 0)
1826066ea43fSLisandro Dalcin         nodeMap[mesh->vertexMap[n]] = n;
18270598e1a2SLisandro Dalcin     for (v = 0; v < numVerts; ++v) {
1828066ea43fSLisandro Dalcin       PetscInt off, node = nodeMap[v];
18290598e1a2SLisandro Dalcin       ierr = PetscSectionGetOffset(coordSection, numCells + v, &off);CHKERRQ(ierr);
18300598e1a2SLisandro Dalcin       for (d = 0; d < coordDim; ++d)
1831066ea43fSLisandro Dalcin         pointCoords[off+d] = (PetscReal) coords[node*3+d];
18320598e1a2SLisandro Dalcin     }
1833066ea43fSLisandro Dalcin     ierr = PetscFree(nodeMap);CHKERRQ(ierr);
1834066ea43fSLisandro Dalcin     ierr = VecRestoreArray(coordinates, &pointCoords);CHKERRQ(ierr);
1835066ea43fSLisandro Dalcin 
1836066ea43fSLisandro Dalcin   }
1837066ea43fSLisandro Dalcin 
1838066ea43fSLisandro Dalcin   ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr);
1839066ea43fSLisandro Dalcin   ierr = VecSetBlockSize(coordinates, coordDim);CHKERRQ(ierr);
1840331830f3SMatthew G. Knepley   ierr = DMSetCoordinatesLocal(*dm, coordinates);CHKERRQ(ierr);
18410598e1a2SLisandro Dalcin   ierr = VecDestroy(&coordinates);CHKERRQ(ierr);
184211c56cb0SLisandro Dalcin   ierr = DMSetPeriodicity(*dm, periodic, NULL, NULL, NULL);CHKERRQ(ierr);
184311c56cb0SLisandro Dalcin 
18440598e1a2SLisandro Dalcin   ierr = GmshMeshDestroy(&mesh);CHKERRQ(ierr);
18450598e1a2SLisandro Dalcin   ierr = PetscBTDestroy(&periodicVerts);CHKERRQ(ierr);
18460598e1a2SLisandro Dalcin   ierr = PetscBTDestroy(&periodicCells);CHKERRQ(ierr);
184711c56cb0SLisandro Dalcin 
1848066ea43fSLisandro Dalcin   if (highOrder && project)  {
1849066ea43fSLisandro Dalcin     PetscFE         fe;
1850066ea43fSLisandro Dalcin     const char      prefix[]   = "dm_plex_gmsh_project_";
1851066ea43fSLisandro Dalcin     PetscBool       continuity = periodic ? PETSC_FALSE : PETSC_TRUE;
1852066ea43fSLisandro Dalcin     PetscDTNodeType nodeType   = PETSCDTNODES_GAUSSJACOBI;
1853066ea43fSLisandro Dalcin 
1854066ea43fSLisandro Dalcin     if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */
1855066ea43fSLisandro Dalcin 
1856066ea43fSLisandro Dalcin     ierr = GmshCreateFE(comm, prefix, isSimplex, continuity, nodeType, dim, coordDim, order, &fe);CHKERRQ(ierr);
1857066ea43fSLisandro Dalcin     ierr = PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_project_fe_view");CHKERRQ(ierr);
1858066ea43fSLisandro Dalcin     ierr = DMProjectCoordinates(*dm, fe);CHKERRQ(ierr);
1859066ea43fSLisandro Dalcin     ierr = PetscFEDestroy(&fe);CHKERRQ(ierr);
1860066ea43fSLisandro Dalcin   }
1861066ea43fSLisandro Dalcin 
18620598e1a2SLisandro Dalcin   ierr = PetscLogEventEnd(DMPLEX_CreateGmsh,*dm,NULL,NULL,NULL);CHKERRQ(ierr);
1863331830f3SMatthew G. Knepley   PetscFunctionReturn(0);
1864331830f3SMatthew G. Knepley }
1865