xref: /petsc/src/dm/impls/plex/plexgmsh.c (revision 07c2e4feb6773e78bda63e3a89d5b841667f9670)
1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I   "petscdmplex.h"   I*/
2730356f6SLisandro Dalcin #include <petsc/private/hashmapi.h>
3331830f3SMatthew G. Knepley 
4066ea43fSLisandro Dalcin #include <../src/dm/impls/plex/gmshlex.h>
5066ea43fSLisandro Dalcin 
6066ea43fSLisandro Dalcin #define GMSH_LEXORDER_ITEM(T, p) \
7d71ae5a4SJacob Faibussowitsch   static int *GmshLexOrder_##T##_##p(void) \
8d71ae5a4SJacob Faibussowitsch   { \
9066ea43fSLisandro Dalcin     static int Gmsh_LexOrder_##T##_##p[GmshNumNodes_##T(p)] = {-1}; \
10066ea43fSLisandro Dalcin     int       *lex                                          = Gmsh_LexOrder_##T##_##p; \
11066ea43fSLisandro Dalcin     if (lex[0] == -1) (void)GmshLexOrder_##T(p, lex, 0); \
12066ea43fSLisandro Dalcin     return lex; \
13066ea43fSLisandro Dalcin   }
14066ea43fSLisandro Dalcin 
GmshLexOrder_QUA_2_Serendipity(void)15d71ae5a4SJacob Faibussowitsch static int *GmshLexOrder_QUA_2_Serendipity(void)
16d71ae5a4SJacob Faibussowitsch {
17b9bf55e5SMatthew G. Knepley   static int Gmsh_LexOrder_QUA_2_Serendipity[9] = {-1};
18b9bf55e5SMatthew G. Knepley   int       *lex                                = Gmsh_LexOrder_QUA_2_Serendipity;
19b9bf55e5SMatthew G. Knepley   if (lex[0] == -1) {
20b9bf55e5SMatthew G. Knepley     /* Vertices */
219371c9d4SSatish Balay     lex[0] = 0;
229371c9d4SSatish Balay     lex[2] = 1;
239371c9d4SSatish Balay     lex[8] = 2;
249371c9d4SSatish Balay     lex[6] = 3;
25b9bf55e5SMatthew G. Knepley     /* Edges */
269371c9d4SSatish Balay     lex[1] = 4;
279371c9d4SSatish Balay     lex[5] = 5;
289371c9d4SSatish Balay     lex[7] = 6;
299371c9d4SSatish Balay     lex[3] = 7;
30b9bf55e5SMatthew G. Knepley     /* Cell */
31b9bf55e5SMatthew G. Knepley     lex[4] = -8;
32b9bf55e5SMatthew G. Knepley   }
33b9bf55e5SMatthew G. Knepley   return lex;
34b9bf55e5SMatthew G. Knepley }
35b9bf55e5SMatthew G. Knepley 
GmshLexOrder_HEX_2_Serendipity(void)36d71ae5a4SJacob Faibussowitsch static int *GmshLexOrder_HEX_2_Serendipity(void)
37d71ae5a4SJacob Faibussowitsch {
38b9bf55e5SMatthew G. Knepley   static int Gmsh_LexOrder_HEX_2_Serendipity[27] = {-1};
39b9bf55e5SMatthew G. Knepley   int       *lex                                 = Gmsh_LexOrder_HEX_2_Serendipity;
40b9bf55e5SMatthew G. Knepley   if (lex[0] == -1) {
41b9bf55e5SMatthew G. Knepley     /* Vertices */
429371c9d4SSatish Balay     lex[0]  = 0;
439371c9d4SSatish Balay     lex[2]  = 1;
449371c9d4SSatish Balay     lex[8]  = 2;
459371c9d4SSatish Balay     lex[6]  = 3;
469371c9d4SSatish Balay     lex[18] = 4;
479371c9d4SSatish Balay     lex[20] = 5;
489371c9d4SSatish Balay     lex[26] = 6;
499371c9d4SSatish Balay     lex[24] = 7;
50b9bf55e5SMatthew G. Knepley     /* Edges */
519371c9d4SSatish Balay     lex[1]  = 8;
529371c9d4SSatish Balay     lex[3]  = 9;
539371c9d4SSatish Balay     lex[9]  = 10;
549371c9d4SSatish Balay     lex[5]  = 11;
559371c9d4SSatish Balay     lex[11] = 12;
569371c9d4SSatish Balay     lex[7]  = 13;
579371c9d4SSatish Balay     lex[17] = 14;
589371c9d4SSatish Balay     lex[15] = 15;
599371c9d4SSatish Balay     lex[19] = 16;
609371c9d4SSatish Balay     lex[21] = 17;
619371c9d4SSatish Balay     lex[23] = 18;
629371c9d4SSatish Balay     lex[25] = 19;
63b9bf55e5SMatthew G. Knepley     /* Faces */
649371c9d4SSatish Balay     lex[4]  = -20;
659371c9d4SSatish Balay     lex[10] = -21;
669371c9d4SSatish Balay     lex[12] = -22;
679371c9d4SSatish Balay     lex[14] = -23;
689371c9d4SSatish Balay     lex[16] = -24;
699371c9d4SSatish Balay     lex[22] = -25;
70b9bf55e5SMatthew G. Knepley     /* Cell */
71b9bf55e5SMatthew G. Knepley     lex[13] = -26;
72b9bf55e5SMatthew G. Knepley   }
73b9bf55e5SMatthew G. Knepley   return lex;
74b9bf55e5SMatthew G. Knepley }
75b9bf55e5SMatthew G. Knepley 
76066ea43fSLisandro Dalcin #define GMSH_LEXORDER_LIST(T) \
77066ea43fSLisandro Dalcin   GMSH_LEXORDER_ITEM(T, 1) \
78066ea43fSLisandro Dalcin   GMSH_LEXORDER_ITEM(T, 2) \
79066ea43fSLisandro Dalcin   GMSH_LEXORDER_ITEM(T, 3) \
80066ea43fSLisandro Dalcin   GMSH_LEXORDER_ITEM(T, 4) \
81066ea43fSLisandro Dalcin   GMSH_LEXORDER_ITEM(T, 5) \
82066ea43fSLisandro Dalcin   GMSH_LEXORDER_ITEM(T, 6) \
83066ea43fSLisandro Dalcin   GMSH_LEXORDER_ITEM(T, 7) \
84066ea43fSLisandro Dalcin   GMSH_LEXORDER_ITEM(T, 8) \
85066ea43fSLisandro Dalcin   GMSH_LEXORDER_ITEM(T, 9) \
86066ea43fSLisandro Dalcin   GMSH_LEXORDER_ITEM(T, 10)
87066ea43fSLisandro Dalcin 
88066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(VTX, 0)
89066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(SEG)
90066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(TRI)
91066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(QUA)
92066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(TET)
93066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(HEX)
94066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(PRI)
95066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(PYR)
96066ea43fSLisandro Dalcin 
97066ea43fSLisandro Dalcin typedef enum {
98066ea43fSLisandro Dalcin   GMSH_VTX           = 0,
99066ea43fSLisandro Dalcin   GMSH_SEG           = 1,
100066ea43fSLisandro Dalcin   GMSH_TRI           = 2,
101066ea43fSLisandro Dalcin   GMSH_QUA           = 3,
102066ea43fSLisandro Dalcin   GMSH_TET           = 4,
103066ea43fSLisandro Dalcin   GMSH_HEX           = 5,
104066ea43fSLisandro Dalcin   GMSH_PRI           = 6,
105066ea43fSLisandro Dalcin   GMSH_PYR           = 7,
106066ea43fSLisandro Dalcin   GMSH_NUM_POLYTOPES = 8
107066ea43fSLisandro Dalcin } GmshPolytopeType;
108066ea43fSLisandro Dalcin 
109de78e4feSLisandro Dalcin typedef struct {
1100598e1a2SLisandro Dalcin   int cellType;
111066ea43fSLisandro Dalcin   int polytope;
1120598e1a2SLisandro Dalcin   int dim;
1130598e1a2SLisandro Dalcin   int order;
114066ea43fSLisandro Dalcin   int numVerts;
1150598e1a2SLisandro Dalcin   int numNodes;
116066ea43fSLisandro Dalcin   int *(*lexorder)(void);
1170598e1a2SLisandro Dalcin } GmshCellInfo;
1180598e1a2SLisandro Dalcin 
11910dd146fSPierre Jolivet #define GmshCellEntry(cellType, polytope, dim, order) {cellType, GMSH_##polytope, dim, order, GmshNumNodes_##polytope(1), GmshNumNodes_##polytope(order), GmshLexOrder_##polytope##_##order}
1200598e1a2SLisandro Dalcin 
1210598e1a2SLisandro Dalcin static const GmshCellInfo GmshCellTable[] = {
122066ea43fSLisandro Dalcin   GmshCellEntry(15, VTX, 0, 0),
1230598e1a2SLisandro Dalcin 
1249371c9d4SSatish Balay   GmshCellEntry(1, SEG, 1, 1),   GmshCellEntry(8, SEG, 1, 2),   GmshCellEntry(26, SEG, 1, 3),
1259371c9d4SSatish Balay   GmshCellEntry(27, SEG, 1, 4),  GmshCellEntry(28, SEG, 1, 5),  GmshCellEntry(62, SEG, 1, 6),
1269371c9d4SSatish Balay   GmshCellEntry(63, SEG, 1, 7),  GmshCellEntry(64, SEG, 1, 8),  GmshCellEntry(65, SEG, 1, 9),
127066ea43fSLisandro Dalcin   GmshCellEntry(66, SEG, 1, 10),
1280598e1a2SLisandro Dalcin 
1299371c9d4SSatish Balay   GmshCellEntry(2, TRI, 2, 1),   GmshCellEntry(9, TRI, 2, 2),   GmshCellEntry(21, TRI, 2, 3),
1309371c9d4SSatish Balay   GmshCellEntry(23, TRI, 2, 4),  GmshCellEntry(25, TRI, 2, 5),  GmshCellEntry(42, TRI, 2, 6),
1319371c9d4SSatish Balay   GmshCellEntry(43, TRI, 2, 7),  GmshCellEntry(44, TRI, 2, 8),  GmshCellEntry(45, TRI, 2, 9),
132066ea43fSLisandro Dalcin   GmshCellEntry(46, TRI, 2, 10),
1330598e1a2SLisandro Dalcin 
1349371c9d4SSatish Balay   GmshCellEntry(3, QUA, 2, 1),   GmshCellEntry(10, QUA, 2, 2),  {16, GMSH_QUA, 2, 2, 4, 8,  GmshLexOrder_QUA_2_Serendipity},
1359371c9d4SSatish Balay   GmshCellEntry(36, QUA, 2, 3),  GmshCellEntry(37, QUA, 2, 4),  GmshCellEntry(38, QUA, 2, 5),
1369371c9d4SSatish Balay   GmshCellEntry(47, QUA, 2, 6),  GmshCellEntry(48, QUA, 2, 7),  GmshCellEntry(49, QUA, 2, 8),
1379371c9d4SSatish Balay   GmshCellEntry(50, QUA, 2, 9),  GmshCellEntry(51, QUA, 2, 10),
1380598e1a2SLisandro Dalcin 
1399371c9d4SSatish Balay   GmshCellEntry(4, TET, 3, 1),   GmshCellEntry(11, TET, 3, 2),  GmshCellEntry(29, TET, 3, 3),
1409371c9d4SSatish Balay   GmshCellEntry(30, TET, 3, 4),  GmshCellEntry(31, TET, 3, 5),  GmshCellEntry(71, TET, 3, 6),
1419371c9d4SSatish Balay   GmshCellEntry(72, TET, 3, 7),  GmshCellEntry(73, TET, 3, 8),  GmshCellEntry(74, TET, 3, 9),
142066ea43fSLisandro Dalcin   GmshCellEntry(75, TET, 3, 10),
1430598e1a2SLisandro Dalcin 
1449371c9d4SSatish Balay   GmshCellEntry(5, HEX, 3, 1),   GmshCellEntry(12, HEX, 3, 2),  {17, GMSH_HEX, 3, 2, 8, 20, GmshLexOrder_HEX_2_Serendipity},
1459371c9d4SSatish Balay   GmshCellEntry(92, HEX, 3, 3),  GmshCellEntry(93, HEX, 3, 4),  GmshCellEntry(94, HEX, 3, 5),
1469371c9d4SSatish Balay   GmshCellEntry(95, HEX, 3, 6),  GmshCellEntry(96, HEX, 3, 7),  GmshCellEntry(97, HEX, 3, 8),
1479371c9d4SSatish Balay   GmshCellEntry(98, HEX, 3, 9),  GmshCellEntry(-1, HEX, 3, 10),
1480598e1a2SLisandro Dalcin 
1499371c9d4SSatish Balay   GmshCellEntry(6, PRI, 3, 1),   GmshCellEntry(13, PRI, 3, 2),  GmshCellEntry(90, PRI, 3, 3),
1509371c9d4SSatish Balay   GmshCellEntry(91, PRI, 3, 4),  GmshCellEntry(106, PRI, 3, 5), GmshCellEntry(107, PRI, 3, 6),
1519371c9d4SSatish Balay   GmshCellEntry(108, PRI, 3, 7), GmshCellEntry(109, PRI, 3, 8), GmshCellEntry(110, PRI, 3, 9),
152066ea43fSLisandro Dalcin   GmshCellEntry(-1, PRI, 3, 10),
1530598e1a2SLisandro Dalcin 
1549371c9d4SSatish Balay   GmshCellEntry(7, PYR, 3, 1),   GmshCellEntry(14, PYR, 3, 2),  GmshCellEntry(118, PYR, 3, 3),
1559371c9d4SSatish Balay   GmshCellEntry(119, PYR, 3, 4), GmshCellEntry(120, PYR, 3, 5), GmshCellEntry(121, PYR, 3, 6),
1569371c9d4SSatish Balay   GmshCellEntry(122, PYR, 3, 7), GmshCellEntry(123, PYR, 3, 8), GmshCellEntry(124, PYR, 3, 9),
157066ea43fSLisandro Dalcin   GmshCellEntry(-1, PYR, 3, 10)
1580598e1a2SLisandro Dalcin 
1590598e1a2SLisandro Dalcin #if 0
160066ea43fSLisandro Dalcin   {20, GMSH_TRI, 2, 3, 3,  9, NULL},
161066ea43fSLisandro Dalcin   {18, GMSH_PRI, 3, 2, 6, 15, NULL},
162066ea43fSLisandro Dalcin   {19, GMSH_PYR, 3, 2, 5, 13, NULL},
1630598e1a2SLisandro Dalcin #endif
1640598e1a2SLisandro Dalcin };
1650598e1a2SLisandro Dalcin 
1660598e1a2SLisandro Dalcin static GmshCellInfo GmshCellMap[150];
1670598e1a2SLisandro Dalcin 
GmshCellInfoSetUp(void)168d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshCellInfoSetUp(void)
169d71ae5a4SJacob Faibussowitsch {
1700598e1a2SLisandro Dalcin   size_t           i, n;
1710598e1a2SLisandro Dalcin   static PetscBool called = PETSC_FALSE;
1720598e1a2SLisandro Dalcin 
1730598e1a2SLisandro Dalcin   PetscFunctionBegin;
1744d86920dSPierre Jolivet   if (called) PetscFunctionReturn(PETSC_SUCCESS);
1750598e1a2SLisandro Dalcin   called = PETSC_TRUE;
176dd39110bSPierre Jolivet   n      = PETSC_STATIC_ARRAY_LENGTH(GmshCellMap);
1770598e1a2SLisandro Dalcin   for (i = 0; i < n; ++i) {
1780598e1a2SLisandro Dalcin     GmshCellMap[i].cellType = -1;
179066ea43fSLisandro Dalcin     GmshCellMap[i].polytope = -1;
1800598e1a2SLisandro Dalcin   }
181dd39110bSPierre Jolivet   n = PETSC_STATIC_ARRAY_LENGTH(GmshCellTable);
182066ea43fSLisandro Dalcin   for (i = 0; i < n; ++i) {
183066ea43fSLisandro Dalcin     if (GmshCellTable[i].cellType <= 0) continue;
184066ea43fSLisandro Dalcin     GmshCellMap[GmshCellTable[i].cellType] = GmshCellTable[i];
185066ea43fSLisandro Dalcin   }
1863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1870598e1a2SLisandro Dalcin }
1880598e1a2SLisandro Dalcin 
1899371c9d4SSatish Balay #define GmshCellTypeCheck(ct) \
1909371c9d4SSatish Balay   PetscMacroReturnStandard(const int _ct_ = (int)ct; PetscCheck(_ct_ >= 0 && _ct_ < (int)PETSC_STATIC_ARRAY_LENGTH(GmshCellMap), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid Gmsh element type %d", _ct_); PetscCheck(GmshCellMap[_ct_].cellType == _ct_, PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported Gmsh element type %d", _ct_); \
1919371c9d4SSatish Balay                            PetscCheck(GmshCellMap[_ct_].polytope != -1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported Gmsh element type %d", _ct_);)
1920598e1a2SLisandro Dalcin 
1930598e1a2SLisandro Dalcin typedef struct {
194698a79b9SLisandro Dalcin   PetscViewer viewer;
195698a79b9SLisandro Dalcin   int         fileFormat;
196698a79b9SLisandro Dalcin   int         dataSize;
197698a79b9SLisandro Dalcin   PetscBool   binary;
198698a79b9SLisandro Dalcin   PetscBool   byteSwap;
199698a79b9SLisandro Dalcin   size_t      wlen;
200698a79b9SLisandro Dalcin   void       *wbuf;
201698a79b9SLisandro Dalcin   size_t      slen;
202698a79b9SLisandro Dalcin   void       *sbuf;
2030598e1a2SLisandro Dalcin   PetscInt   *nbuf;
2040598e1a2SLisandro Dalcin   PetscInt    nodeStart;
2050598e1a2SLisandro Dalcin   PetscInt    nodeEnd;
20633a088b6SMatthew G. Knepley   PetscInt   *nodeMap;
207698a79b9SLisandro Dalcin } GmshFile;
208de78e4feSLisandro Dalcin 
2096497c311SBarry Smith /*
2106497c311SBarry Smith    Returns an array of count items each with a sizeof(eltsize)
2116497c311SBarry Smith */
GmshBufferGet(GmshFile * gmsh,PetscCount count,size_t eltsize,void * buf)2126497c311SBarry Smith static PetscErrorCode GmshBufferGet(GmshFile *gmsh, PetscCount count, size_t eltsize, void *buf)
213d71ae5a4SJacob Faibussowitsch {
214de78e4feSLisandro Dalcin   size_t size = count * eltsize;
21511c56cb0SLisandro Dalcin 
21611c56cb0SLisandro Dalcin   PetscFunctionBegin;
217698a79b9SLisandro Dalcin   if (gmsh->wlen < size) {
2189566063dSJacob Faibussowitsch     PetscCall(PetscFree(gmsh->wbuf));
2199566063dSJacob Faibussowitsch     PetscCall(PetscMalloc(size, &gmsh->wbuf));
220698a79b9SLisandro Dalcin     gmsh->wlen = size;
221de78e4feSLisandro Dalcin   }
222698a79b9SLisandro Dalcin   *(void **)buf = size ? gmsh->wbuf : NULL;
2233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
224de78e4feSLisandro Dalcin }
225de78e4feSLisandro Dalcin 
2266497c311SBarry Smith /*
2276497c311SBarry Smith     Returns an array of count items each with the size determined by the GmshFile
2286497c311SBarry Smith */
GmshBufferSizeGet(GmshFile * gmsh,PetscCount count,void * buf)2296497c311SBarry Smith static PetscErrorCode GmshBufferSizeGet(GmshFile *gmsh, PetscCount count, void *buf)
230d71ae5a4SJacob Faibussowitsch {
231698a79b9SLisandro Dalcin   size_t dataSize = (size_t)gmsh->dataSize;
232698a79b9SLisandro Dalcin   size_t size     = count * dataSize;
233698a79b9SLisandro Dalcin 
234698a79b9SLisandro Dalcin   PetscFunctionBegin;
235698a79b9SLisandro Dalcin   if (gmsh->slen < size) {
2369566063dSJacob Faibussowitsch     PetscCall(PetscFree(gmsh->sbuf));
2379566063dSJacob Faibussowitsch     PetscCall(PetscMalloc(size, &gmsh->sbuf));
238698a79b9SLisandro Dalcin     gmsh->slen = size;
239698a79b9SLisandro Dalcin   }
240698a79b9SLisandro Dalcin   *(void **)buf = size ? gmsh->sbuf : NULL;
2413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
242698a79b9SLisandro Dalcin }
243698a79b9SLisandro Dalcin 
2446497c311SBarry Smith /*
2456497c311SBarry Smith     Reads an array of count items each with the size determined by the PetscDataType
2466497c311SBarry Smith */
GmshRead(GmshFile * gmsh,void * buf,PetscCount count,PetscDataType dtype)2476497c311SBarry Smith static PetscErrorCode GmshRead(GmshFile *gmsh, void *buf, PetscCount count, PetscDataType dtype)
248d71ae5a4SJacob Faibussowitsch {
2496497c311SBarry Smith   PetscInt icount;
2506497c311SBarry Smith 
251de78e4feSLisandro Dalcin   PetscFunctionBegin;
2526497c311SBarry Smith   PetscCall(PetscIntCast(count, &icount));
2536497c311SBarry Smith   PetscCall(PetscViewerRead(gmsh->viewer, buf, icount, NULL, dtype));
2546497c311SBarry Smith   if (gmsh->byteSwap) PetscCall(PetscByteSwap(buf, dtype, icount));
2553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
256698a79b9SLisandro Dalcin }
257698a79b9SLisandro Dalcin 
GmshReadString(GmshFile * gmsh,char * buf,PetscCount count)2586497c311SBarry Smith static PetscErrorCode GmshReadString(GmshFile *gmsh, char *buf, PetscCount count)
259d71ae5a4SJacob Faibussowitsch {
2606497c311SBarry Smith   PetscInt icount;
2616497c311SBarry Smith 
262698a79b9SLisandro Dalcin   PetscFunctionBegin;
2636497c311SBarry Smith   PetscCall(PetscIntCast(count, &icount));
2646497c311SBarry Smith   PetscCall(PetscViewerRead(gmsh->viewer, buf, icount, NULL, PETSC_STRING));
2653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
266698a79b9SLisandro Dalcin }
267698a79b9SLisandro Dalcin 
GmshMatch(PETSC_UNUSED GmshFile * gmsh,const char Section[],char line[PETSC_MAX_PATH_LEN],PetscBool * match)268d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshMatch(PETSC_UNUSED GmshFile *gmsh, const char Section[], char line[PETSC_MAX_PATH_LEN], PetscBool *match)
269d71ae5a4SJacob Faibussowitsch {
270d6689ca9SLisandro Dalcin   PetscFunctionBegin;
2719566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(line, Section, match));
2723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
273d6689ca9SLisandro Dalcin }
274d6689ca9SLisandro Dalcin 
GmshExpect(GmshFile * gmsh,const char Section[],char line[PETSC_MAX_PATH_LEN])275d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshExpect(GmshFile *gmsh, const char Section[], char line[PETSC_MAX_PATH_LEN])
276d71ae5a4SJacob Faibussowitsch {
277d6689ca9SLisandro Dalcin   PetscBool match;
278d6689ca9SLisandro Dalcin 
279d6689ca9SLisandro Dalcin   PetscFunctionBegin;
2809566063dSJacob Faibussowitsch   PetscCall(GmshMatch(gmsh, Section, line, &match));
28100045ab3SPierre Jolivet   PetscCheck(match, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file, expecting %s, not %s", Section, line);
2823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
283d6689ca9SLisandro Dalcin }
284d6689ca9SLisandro Dalcin 
GmshReadSection(GmshFile * gmsh,char line[PETSC_MAX_PATH_LEN])285d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadSection(GmshFile *gmsh, char line[PETSC_MAX_PATH_LEN])
286d71ae5a4SJacob Faibussowitsch {
287d6689ca9SLisandro Dalcin   PetscBool match;
288d6689ca9SLisandro Dalcin 
289d6689ca9SLisandro Dalcin   PetscFunctionBegin;
290d6689ca9SLisandro Dalcin   while (PETSC_TRUE) {
2919566063dSJacob Faibussowitsch     PetscCall(GmshReadString(gmsh, line, 1));
2929566063dSJacob Faibussowitsch     PetscCall(GmshMatch(gmsh, "$Comments", line, &match));
293d6689ca9SLisandro Dalcin     if (!match) break;
294d6689ca9SLisandro Dalcin     while (PETSC_TRUE) {
2959566063dSJacob Faibussowitsch       PetscCall(GmshReadString(gmsh, line, 1));
2969566063dSJacob Faibussowitsch       PetscCall(GmshMatch(gmsh, "$EndComments", line, &match));
297d6689ca9SLisandro Dalcin       if (match) break;
298d6689ca9SLisandro Dalcin     }
299d6689ca9SLisandro Dalcin   }
3003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
301d6689ca9SLisandro Dalcin }
302d6689ca9SLisandro Dalcin 
GmshReadEndSection(GmshFile * gmsh,const char EndSection[],char line[PETSC_MAX_PATH_LEN])303d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEndSection(GmshFile *gmsh, const char EndSection[], char line[PETSC_MAX_PATH_LEN])
304d71ae5a4SJacob Faibussowitsch {
305d6689ca9SLisandro Dalcin   PetscFunctionBegin;
3069566063dSJacob Faibussowitsch   PetscCall(GmshReadString(gmsh, line, 1));
3079566063dSJacob Faibussowitsch   PetscCall(GmshExpect(gmsh, EndSection, line));
3083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
309d6689ca9SLisandro Dalcin }
310d6689ca9SLisandro Dalcin 
3116497c311SBarry Smith /*
3126497c311SBarry Smith      Read into buf[] count number of PetscInt integers (the file storage size may be different than PetscInt)
3136497c311SBarry Smith */
GmshReadPetscInt(GmshFile * gmsh,PetscInt * buf,PetscCount count)3146497c311SBarry Smith static PetscErrorCode GmshReadPetscInt(GmshFile *gmsh, PetscInt *buf, PetscCount count)
315d71ae5a4SJacob Faibussowitsch {
3166497c311SBarry Smith   PetscCount i;
317698a79b9SLisandro Dalcin   size_t     dataSize = (size_t)gmsh->dataSize;
318698a79b9SLisandro Dalcin 
319698a79b9SLisandro Dalcin   PetscFunctionBegin;
320698a79b9SLisandro Dalcin   if (dataSize == sizeof(PetscInt)) {
3219566063dSJacob Faibussowitsch     PetscCall(GmshRead(gmsh, buf, count, PETSC_INT));
322698a79b9SLisandro Dalcin   } else if (dataSize == sizeof(int)) {
323698a79b9SLisandro Dalcin     int *ibuf = NULL;
3249566063dSJacob Faibussowitsch     PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf));
3259566063dSJacob Faibussowitsch     PetscCall(GmshRead(gmsh, ibuf, count, PETSC_ENUM));
326698a79b9SLisandro Dalcin     for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i];
327698a79b9SLisandro Dalcin   } else if (dataSize == sizeof(long)) {
328698a79b9SLisandro Dalcin     long *ibuf = NULL;
3299566063dSJacob Faibussowitsch     PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf));
3309566063dSJacob Faibussowitsch     PetscCall(GmshRead(gmsh, ibuf, count, PETSC_LONG));
331698a79b9SLisandro Dalcin     for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i];
332698a79b9SLisandro Dalcin   } else if (dataSize == sizeof(PetscInt64)) {
333698a79b9SLisandro Dalcin     PetscInt64 *ibuf = NULL;
3349566063dSJacob Faibussowitsch     PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf));
3359566063dSJacob Faibussowitsch     PetscCall(GmshRead(gmsh, ibuf, count, PETSC_INT64));
336698a79b9SLisandro Dalcin     for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i];
337698a79b9SLisandro Dalcin   }
3383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
339698a79b9SLisandro Dalcin }
340698a79b9SLisandro Dalcin 
3416497c311SBarry Smith /*
3426497c311SBarry Smith      Read into buf[] count number of PetscCount integers  (the file storage size may be different than PetscCount)
3436497c311SBarry Smith */
GmshReadPetscCount(GmshFile * gmsh,PetscCount * buf,PetscCount count)3446497c311SBarry Smith static PetscErrorCode GmshReadPetscCount(GmshFile *gmsh, PetscCount *buf, PetscCount count)
3456497c311SBarry Smith {
3466497c311SBarry Smith   PetscCount i;
3476497c311SBarry Smith   size_t     dataSize = (size_t)gmsh->dataSize;
3486497c311SBarry Smith 
3496497c311SBarry Smith   PetscFunctionBegin;
3506497c311SBarry Smith   if (dataSize == sizeof(PetscCount)) {
3516497c311SBarry Smith     PetscCall(GmshRead(gmsh, buf, count, PETSC_COUNT));
3526497c311SBarry Smith   } else if (dataSize == sizeof(int)) {
3536497c311SBarry Smith     int *ibuf = NULL;
3546497c311SBarry Smith     PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf));
3556497c311SBarry Smith     PetscCall(GmshRead(gmsh, ibuf, count, PETSC_ENUM));
3566497c311SBarry Smith     for (i = 0; i < count; ++i) buf[i] = (PetscCount)ibuf[i];
3576497c311SBarry Smith   } else if (dataSize == sizeof(long)) {
3586497c311SBarry Smith     long *ibuf = NULL;
3596497c311SBarry Smith     PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf));
3606497c311SBarry Smith     PetscCall(GmshRead(gmsh, ibuf, count, PETSC_LONG));
3616497c311SBarry Smith     for (i = 0; i < count; ++i) buf[i] = (PetscCount)ibuf[i];
3626497c311SBarry Smith   } else if (dataSize == sizeof(PetscInt64)) {
3636497c311SBarry Smith     PetscInt64 *ibuf = NULL;
3646497c311SBarry Smith     PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf));
3656497c311SBarry Smith     PetscCall(GmshRead(gmsh, ibuf, count, PETSC_INT64));
3666497c311SBarry Smith     for (i = 0; i < count; ++i) buf[i] = (PetscCount)ibuf[i];
3676497c311SBarry Smith   }
3686497c311SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
3696497c311SBarry Smith }
3706497c311SBarry Smith 
3716497c311SBarry Smith /*
3726497c311SBarry Smith      Read into buf[] count number of PetscEnum integers
3736497c311SBarry Smith */
GmshReadInt(GmshFile * gmsh,int * buf,PetscCount count)3746497c311SBarry Smith static PetscErrorCode GmshReadInt(GmshFile *gmsh, int *buf, PetscCount count)
375d71ae5a4SJacob Faibussowitsch {
376698a79b9SLisandro Dalcin   PetscFunctionBegin;
3779566063dSJacob Faibussowitsch   PetscCall(GmshRead(gmsh, buf, count, PETSC_ENUM));
3783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
379698a79b9SLisandro Dalcin }
380698a79b9SLisandro Dalcin 
3816497c311SBarry Smith /*
3826497c311SBarry Smith      Read into buf[] count number of double
3836497c311SBarry Smith */
GmshReadDouble(GmshFile * gmsh,double * buf,PetscCount count)3846497c311SBarry Smith static PetscErrorCode GmshReadDouble(GmshFile *gmsh, double *buf, PetscCount count)
385d71ae5a4SJacob Faibussowitsch {
386698a79b9SLisandro Dalcin   PetscFunctionBegin;
3879566063dSJacob Faibussowitsch   PetscCall(GmshRead(gmsh, buf, count, PETSC_DOUBLE));
3883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
389de78e4feSLisandro Dalcin }
390de78e4feSLisandro Dalcin 
3919c0edc59SMatthew G. Knepley #define GMSH_MAX_TAGS 16
3927d5b9244SMatthew G. Knepley 
393de78e4feSLisandro Dalcin typedef struct {
3940598e1a2SLisandro Dalcin   PetscInt id;                  /* Entity ID */
3950598e1a2SLisandro Dalcin   PetscInt dim;                 /* Dimension */
396de78e4feSLisandro Dalcin   double   bbox[6];             /* Bounding box */
397de78e4feSLisandro Dalcin   PetscInt numTags;             /* Size of tag array */
3987d5b9244SMatthew G. Knepley   int      tags[GMSH_MAX_TAGS]; /* Tag array */
399de78e4feSLisandro Dalcin } GmshEntity;
400de78e4feSLisandro Dalcin 
401de78e4feSLisandro Dalcin typedef struct {
402730356f6SLisandro Dalcin   GmshEntity *entity[4];
403730356f6SLisandro Dalcin   PetscHMapI  entityMap[4];
404730356f6SLisandro Dalcin } GmshEntities;
405730356f6SLisandro Dalcin 
GmshEntitiesCreate(PetscCount count[4],GmshEntities ** entities)4066497c311SBarry Smith static PetscErrorCode GmshEntitiesCreate(PetscCount count[4], GmshEntities **entities)
407d71ae5a4SJacob Faibussowitsch {
408730356f6SLisandro Dalcin   PetscFunctionBegin;
4099566063dSJacob Faibussowitsch   PetscCall(PetscNew(entities));
4106497c311SBarry Smith   for (PetscInt dim = 0; dim < 4; ++dim) {
4119566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(count[dim], &(*entities)->entity[dim]));
4129566063dSJacob Faibussowitsch     PetscCall(PetscHMapICreate(&(*entities)->entityMap[dim]));
413730356f6SLisandro Dalcin   }
4143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
415730356f6SLisandro Dalcin }
416730356f6SLisandro Dalcin 
GmshEntitiesDestroy(GmshEntities ** entities)417d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshEntitiesDestroy(GmshEntities **entities)
418d71ae5a4SJacob Faibussowitsch {
4190598e1a2SLisandro Dalcin   PetscInt dim;
4200598e1a2SLisandro Dalcin 
4210598e1a2SLisandro Dalcin   PetscFunctionBegin;
4223ba16761SJacob Faibussowitsch   if (!*entities) PetscFunctionReturn(PETSC_SUCCESS);
4230598e1a2SLisandro Dalcin   for (dim = 0; dim < 4; ++dim) {
4249566063dSJacob Faibussowitsch     PetscCall(PetscFree((*entities)->entity[dim]));
4259566063dSJacob Faibussowitsch     PetscCall(PetscHMapIDestroy(&(*entities)->entityMap[dim]));
4260598e1a2SLisandro Dalcin   }
427f4f49eeaSPierre Jolivet   PetscCall(PetscFree(*entities));
4283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4290598e1a2SLisandro Dalcin }
4300598e1a2SLisandro Dalcin 
GmshEntitiesAdd(GmshEntities * entities,PetscInt index,PetscInt dim,PetscInt eid,GmshEntity ** entity)431d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshEntitiesAdd(GmshEntities *entities, PetscInt index, PetscInt dim, PetscInt eid, GmshEntity **entity)
432d71ae5a4SJacob Faibussowitsch {
433730356f6SLisandro Dalcin   PetscFunctionBegin;
4349566063dSJacob Faibussowitsch   PetscCall(PetscHMapISet(entities->entityMap[dim], eid, index));
435730356f6SLisandro Dalcin   entities->entity[dim][index].dim = dim;
436730356f6SLisandro Dalcin   entities->entity[dim][index].id  = eid;
437730356f6SLisandro Dalcin   if (entity) *entity = &entities->entity[dim][index];
4383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
439730356f6SLisandro Dalcin }
440730356f6SLisandro Dalcin 
GmshEntitiesGet(GmshEntities * entities,PetscInt dim,PetscInt eid,GmshEntity ** entity)441d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshEntitiesGet(GmshEntities *entities, PetscInt dim, PetscInt eid, GmshEntity **entity)
442d71ae5a4SJacob Faibussowitsch {
443730356f6SLisandro Dalcin   PetscInt index;
444730356f6SLisandro Dalcin 
445730356f6SLisandro Dalcin   PetscFunctionBegin;
4469566063dSJacob Faibussowitsch   PetscCall(PetscHMapIGet(entities->entityMap[dim], eid, &index));
447730356f6SLisandro Dalcin   *entity = &entities->entity[dim][index];
4483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
449730356f6SLisandro Dalcin }
450730356f6SLisandro Dalcin 
4510598e1a2SLisandro Dalcin typedef struct {
4520598e1a2SLisandro Dalcin   PetscInt *id;  /* Node IDs */
4530598e1a2SLisandro Dalcin   double   *xyz; /* Coordinates */
45481a1af93SMatthew G. Knepley   PetscInt *tag; /* Physical tag */
4550598e1a2SLisandro Dalcin } GmshNodes;
4560598e1a2SLisandro Dalcin 
GmshNodesCreate(PetscCount count,GmshNodes ** nodes)4576497c311SBarry Smith static PetscErrorCode GmshNodesCreate(PetscCount count, GmshNodes **nodes)
458d71ae5a4SJacob Faibussowitsch {
459730356f6SLisandro Dalcin   PetscFunctionBegin;
4609566063dSJacob Faibussowitsch   PetscCall(PetscNew(nodes));
4619566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(count * 1, &(*nodes)->id));
4629566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(count * 3, &(*nodes)->xyz));
4637d5b9244SMatthew G. Knepley   PetscCall(PetscMalloc1(count * GMSH_MAX_TAGS, &(*nodes)->tag));
4643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
465730356f6SLisandro Dalcin }
4660598e1a2SLisandro Dalcin 
GmshNodesDestroy(GmshNodes ** nodes)467d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshNodesDestroy(GmshNodes **nodes)
468d71ae5a4SJacob Faibussowitsch {
4690598e1a2SLisandro Dalcin   PetscFunctionBegin;
4703ba16761SJacob Faibussowitsch   if (!*nodes) PetscFunctionReturn(PETSC_SUCCESS);
4719566063dSJacob Faibussowitsch   PetscCall(PetscFree((*nodes)->id));
4729566063dSJacob Faibussowitsch   PetscCall(PetscFree((*nodes)->xyz));
4739566063dSJacob Faibussowitsch   PetscCall(PetscFree((*nodes)->tag));
474f4f49eeaSPierre Jolivet   PetscCall(PetscFree(*nodes));
4753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
476730356f6SLisandro Dalcin }
477730356f6SLisandro Dalcin 
478730356f6SLisandro Dalcin typedef struct {
4790598e1a2SLisandro Dalcin   PetscInt  id;                  /* Element ID */
4800598e1a2SLisandro Dalcin   PetscInt  dim;                 /* Dimension */
481de78e4feSLisandro Dalcin   PetscInt  cellType;            /* Cell type */
4820598e1a2SLisandro Dalcin   PetscInt  numVerts;            /* Size of vertex array */
483de78e4feSLisandro Dalcin   PetscInt  numNodes;            /* Size of node array */
4840598e1a2SLisandro Dalcin   PetscInt *nodes;               /* Vertex/Node array */
48581a1af93SMatthew G. Knepley   PetscInt  numTags;             /* Size of physical tag array */
4867d5b9244SMatthew G. Knepley   int       tags[GMSH_MAX_TAGS]; /* Physical tag array */
487de78e4feSLisandro Dalcin } GmshElement;
488de78e4feSLisandro Dalcin 
GmshElementsCreate(PetscCount count,GmshElement ** elements)4896497c311SBarry Smith static PetscErrorCode GmshElementsCreate(PetscCount count, GmshElement **elements)
490d71ae5a4SJacob Faibussowitsch {
4910598e1a2SLisandro Dalcin   PetscFunctionBegin;
4929566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(count, elements));
4933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4940598e1a2SLisandro Dalcin }
4950598e1a2SLisandro Dalcin 
GmshElementsDestroy(GmshElement ** elements)496d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshElementsDestroy(GmshElement **elements)
497d71ae5a4SJacob Faibussowitsch {
4980598e1a2SLisandro Dalcin   PetscFunctionBegin;
4993ba16761SJacob Faibussowitsch   if (!*elements) PetscFunctionReturn(PETSC_SUCCESS);
5009566063dSJacob Faibussowitsch   PetscCall(PetscFree(*elements));
5013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5020598e1a2SLisandro Dalcin }
5030598e1a2SLisandro Dalcin 
5040598e1a2SLisandro Dalcin typedef struct {
5050598e1a2SLisandro Dalcin   PetscInt       dim;
506066ea43fSLisandro Dalcin   PetscInt       order;
5070598e1a2SLisandro Dalcin   GmshEntities  *entities;
5080598e1a2SLisandro Dalcin   PetscInt       numNodes;
5090598e1a2SLisandro Dalcin   GmshNodes     *nodelist;
5100598e1a2SLisandro Dalcin   PetscInt       numElems;
5110598e1a2SLisandro Dalcin   GmshElement   *elements;
5120598e1a2SLisandro Dalcin   PetscInt       numVerts;
5130598e1a2SLisandro Dalcin   PetscInt       numCells;
5140598e1a2SLisandro Dalcin   PetscInt      *periodMap;
5150598e1a2SLisandro Dalcin   PetscInt      *vertexMap;
5160598e1a2SLisandro Dalcin   PetscSegBuffer segbuf;
517a45dabc8SMatthew G. Knepley   PetscInt       numRegions;
51890d778b8SLisandro Dalcin   PetscInt      *regionDims;
519a45dabc8SMatthew G. Knepley   PetscInt      *regionTags;
520a45dabc8SMatthew G. Knepley   char         **regionNames;
5210598e1a2SLisandro Dalcin } GmshMesh;
5220598e1a2SLisandro Dalcin 
GmshMeshCreate(GmshMesh ** mesh)523d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshMeshCreate(GmshMesh **mesh)
524d71ae5a4SJacob Faibussowitsch {
5250598e1a2SLisandro Dalcin   PetscFunctionBegin;
5269566063dSJacob Faibussowitsch   PetscCall(PetscNew(mesh));
5279566063dSJacob Faibussowitsch   PetscCall(PetscSegBufferCreate(sizeof(PetscInt), 0, &(*mesh)->segbuf));
5283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5290598e1a2SLisandro Dalcin }
5300598e1a2SLisandro Dalcin 
GmshMeshDestroy(GmshMesh ** mesh)531d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshMeshDestroy(GmshMesh **mesh)
532d71ae5a4SJacob Faibussowitsch {
533a45dabc8SMatthew G. Knepley   PetscInt r;
5340598e1a2SLisandro Dalcin 
5350598e1a2SLisandro Dalcin   PetscFunctionBegin;
5363ba16761SJacob Faibussowitsch   if (!*mesh) PetscFunctionReturn(PETSC_SUCCESS);
5379566063dSJacob Faibussowitsch   PetscCall(GmshEntitiesDestroy(&(*mesh)->entities));
5389566063dSJacob Faibussowitsch   PetscCall(GmshNodesDestroy(&(*mesh)->nodelist));
5399566063dSJacob Faibussowitsch   PetscCall(GmshElementsDestroy(&(*mesh)->elements));
5409566063dSJacob Faibussowitsch   PetscCall(PetscFree((*mesh)->periodMap));
5419566063dSJacob Faibussowitsch   PetscCall(PetscFree((*mesh)->vertexMap));
5429566063dSJacob Faibussowitsch   PetscCall(PetscSegBufferDestroy(&(*mesh)->segbuf));
5439566063dSJacob Faibussowitsch   for (r = 0; r < (*mesh)->numRegions; ++r) PetscCall(PetscFree((*mesh)->regionNames[r]));
54490d778b8SLisandro Dalcin   PetscCall(PetscFree3((*mesh)->regionDims, (*mesh)->regionTags, (*mesh)->regionNames));
545f4f49eeaSPierre Jolivet   PetscCall(PetscFree(*mesh));
5463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5470598e1a2SLisandro Dalcin }
5480598e1a2SLisandro Dalcin 
GmshReadNodes_v22(GmshFile * gmsh,GmshMesh * mesh)549d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes_v22(GmshFile *gmsh, GmshMesh *mesh)
550d71ae5a4SJacob Faibussowitsch {
551698a79b9SLisandro Dalcin   PetscViewer viewer   = gmsh->viewer;
552698a79b9SLisandro Dalcin   PetscBool   byteSwap = gmsh->byteSwap;
553de78e4feSLisandro Dalcin   char        line[PETSC_MAX_PATH_LEN];
5547d5b9244SMatthew G. Knepley   int         n, t, num, nid, snum;
5550598e1a2SLisandro Dalcin   GmshNodes  *nodes;
556de78e4feSLisandro Dalcin 
557de78e4feSLisandro Dalcin   PetscFunctionBegin;
5589566063dSJacob Faibussowitsch   PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING));
559698a79b9SLisandro Dalcin   snum = sscanf(line, "%d", &num);
56008401ef6SPierre Jolivet   PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
5619566063dSJacob Faibussowitsch   PetscCall(GmshNodesCreate(num, &nodes));
5620598e1a2SLisandro Dalcin   mesh->numNodes = num;
5630598e1a2SLisandro Dalcin   mesh->nodelist = nodes;
5640598e1a2SLisandro Dalcin   for (n = 0; n < num; ++n) {
5650598e1a2SLisandro Dalcin     double *xyz = nodes->xyz + n * 3;
5669566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM));
5679566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE));
5689566063dSJacob Faibussowitsch     if (byteSwap) PetscCall(PetscByteSwap(&nid, PETSC_ENUM, 1));
5699566063dSJacob Faibussowitsch     if (byteSwap) PetscCall(PetscByteSwap(xyz, PETSC_DOUBLE, 3));
5700598e1a2SLisandro Dalcin     nodes->id[n] = nid;
5717d5b9244SMatthew G. Knepley     for (t = 0; t < GMSH_MAX_TAGS; ++t) nodes->tag[n * GMSH_MAX_TAGS + t] = -1;
57211c56cb0SLisandro Dalcin   }
5733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57411c56cb0SLisandro Dalcin }
57511c56cb0SLisandro Dalcin 
576de78e4feSLisandro Dalcin /* Gmsh elements can be of any dimension/co-dimension, so we need to traverse the
577de78e4feSLisandro Dalcin    file contents multiple times to figure out the true number of cells and facets
578de78e4feSLisandro Dalcin    in the given mesh. To make this more efficient we read the file contents only
579de78e4feSLisandro Dalcin    once and store them in memory, while determining the true number of cells. */
GmshReadElements_v22(GmshFile * gmsh,GmshMesh * mesh)580d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements_v22(GmshFile *gmsh, GmshMesh *mesh)
581d71ae5a4SJacob Faibussowitsch {
582698a79b9SLisandro Dalcin   PetscViewer  viewer   = gmsh->viewer;
583698a79b9SLisandro Dalcin   PetscBool    binary   = gmsh->binary;
584698a79b9SLisandro Dalcin   PetscBool    byteSwap = gmsh->byteSwap;
585de78e4feSLisandro Dalcin   char         line[PETSC_MAX_PATH_LEN];
5860598e1a2SLisandro Dalcin   int          i, c, p, num, ibuf[1 + 4 + 1000], snum;
5870598e1a2SLisandro Dalcin   int          cellType, numElem, numVerts, numNodes, numTags;
588df032b82SMatthew G. Knepley   GmshElement *elements;
5890598e1a2SLisandro Dalcin   PetscInt    *nodeMap = gmsh->nodeMap;
590df032b82SMatthew G. Knepley 
591df032b82SMatthew G. Knepley   PetscFunctionBegin;
5929566063dSJacob Faibussowitsch   PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING));
593698a79b9SLisandro Dalcin   snum = sscanf(line, "%d", &num);
59408401ef6SPierre Jolivet   PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
5959566063dSJacob Faibussowitsch   PetscCall(GmshElementsCreate(num, &elements));
5960598e1a2SLisandro Dalcin   mesh->numElems = num;
5970598e1a2SLisandro Dalcin   mesh->elements = elements;
598698a79b9SLisandro Dalcin   for (c = 0; c < num;) {
5999566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM));
6009566063dSJacob Faibussowitsch     if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, 3));
6010598e1a2SLisandro Dalcin 
6020598e1a2SLisandro Dalcin     cellType = binary ? ibuf[0] : ibuf[1];
6030598e1a2SLisandro Dalcin     numElem  = binary ? ibuf[1] : 1;
604df032b82SMatthew G. Knepley     numTags  = ibuf[2];
6050598e1a2SLisandro Dalcin 
6069566063dSJacob Faibussowitsch     PetscCall(GmshCellTypeCheck(cellType));
6070598e1a2SLisandro Dalcin     numVerts = GmshCellMap[cellType].numVerts;
6080598e1a2SLisandro Dalcin     numNodes = GmshCellMap[cellType].numNodes;
6090598e1a2SLisandro Dalcin 
610df032b82SMatthew G. Knepley     for (i = 0; i < numElem; ++i, ++c) {
6110598e1a2SLisandro Dalcin       GmshElement *element = elements + c;
6120598e1a2SLisandro Dalcin       const int    off = binary ? 0 : 1, nint = 1 + numTags + numNodes - off;
6130598e1a2SLisandro Dalcin       const int   *id = ibuf, *nodes = ibuf + 1 + numTags, *tags = ibuf + 1;
6149566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, ibuf + off, nint, NULL, PETSC_ENUM));
6159566063dSJacob Faibussowitsch       if (byteSwap) PetscCall(PetscByteSwap(ibuf + off, PETSC_ENUM, nint));
6160598e1a2SLisandro Dalcin       element->id       = id[0];
6170598e1a2SLisandro Dalcin       element->dim      = GmshCellMap[cellType].dim;
6180598e1a2SLisandro Dalcin       element->cellType = cellType;
6190598e1a2SLisandro Dalcin       element->numVerts = numVerts;
6200598e1a2SLisandro Dalcin       element->numNodes = numNodes;
6217d5b9244SMatthew G. Knepley       element->numTags  = PetscMin(numTags, GMSH_MAX_TAGS);
6229566063dSJacob Faibussowitsch       PetscCall(PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes));
6230598e1a2SLisandro Dalcin       for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]];
6240598e1a2SLisandro Dalcin       for (p = 0; p < element->numTags; p++) element->tags[p] = tags[p];
625df032b82SMatthew G. Knepley     }
626df032b82SMatthew G. Knepley   }
6273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
628df032b82SMatthew G. Knepley }
6297d282ae0SMichael Lange 
630de78e4feSLisandro Dalcin /*
631de78e4feSLisandro Dalcin $Entities
632de78e4feSLisandro Dalcin   numPoints(unsigned long) numCurves(unsigned long)
633de78e4feSLisandro Dalcin     numSurfaces(unsigned long) numVolumes(unsigned long)
634de78e4feSLisandro Dalcin   // points
635de78e4feSLisandro Dalcin   tag(int) boxMinX(double) boxMinY(double) boxMinZ(double)
636de78e4feSLisandro Dalcin     boxMaxX(double) boxMaxY(double) boxMaxZ(double)
637de78e4feSLisandro Dalcin     numPhysicals(unsigned long) phyisicalTag[...](int)
638de78e4feSLisandro Dalcin   ...
639de78e4feSLisandro Dalcin   // curves
640de78e4feSLisandro Dalcin   tag(int) boxMinX(double) boxMinY(double) boxMinZ(double)
641de78e4feSLisandro Dalcin      boxMaxX(double) boxMaxY(double) boxMaxZ(double)
642de78e4feSLisandro Dalcin      numPhysicals(unsigned long) physicalTag[...](int)
643de78e4feSLisandro Dalcin      numBREPVert(unsigned long) tagBREPVert[...](int)
644de78e4feSLisandro Dalcin   ...
645de78e4feSLisandro Dalcin   // surfaces
646de78e4feSLisandro Dalcin   tag(int) boxMinX(double) boxMinY(double) boxMinZ(double)
647de78e4feSLisandro Dalcin     boxMaxX(double) boxMaxY(double) boxMaxZ(double)
648de78e4feSLisandro Dalcin     numPhysicals(unsigned long) physicalTag[...](int)
649de78e4feSLisandro Dalcin     numBREPCurve(unsigned long) tagBREPCurve[...](int)
650de78e4feSLisandro Dalcin   ...
651de78e4feSLisandro Dalcin   // volumes
652de78e4feSLisandro Dalcin   tag(int) boxMinX(double) boxMinY(double) boxMinZ(double)
653de78e4feSLisandro Dalcin     boxMaxX(double) boxMaxY(double) boxMaxZ(double)
654de78e4feSLisandro Dalcin     numPhysicals(unsigned long) physicalTag[...](int)
655de78e4feSLisandro Dalcin     numBREPSurfaces(unsigned long) tagBREPSurfaces[...](int)
656de78e4feSLisandro Dalcin   ...
657de78e4feSLisandro Dalcin $EndEntities
658de78e4feSLisandro Dalcin */
GmshReadEntities_v40(GmshFile * gmsh,GmshMesh * mesh)659d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEntities_v40(GmshFile *gmsh, GmshMesh *mesh)
660d71ae5a4SJacob Faibussowitsch {
661698a79b9SLisandro Dalcin   PetscViewer viewer   = gmsh->viewer;
662698a79b9SLisandro Dalcin   PetscBool   byteSwap = gmsh->byteSwap;
6636497c311SBarry Smith   long        lnum, lbuf[4];
664730356f6SLisandro Dalcin   int         dim, eid, numTags, *ibuf, t;
6656497c311SBarry Smith   PetscCount  index, count[4];
6666497c311SBarry Smith   PetscInt    i, num;
667a5ba3d71SLisandro Dalcin   GmshEntity *entity = NULL;
668de78e4feSLisandro Dalcin 
669de78e4feSLisandro Dalcin   PetscFunctionBegin;
6709566063dSJacob Faibussowitsch   PetscCall(PetscViewerRead(viewer, lbuf, 4, NULL, PETSC_LONG));
6719566063dSJacob Faibussowitsch   if (byteSwap) PetscCall(PetscByteSwap(lbuf, PETSC_LONG, 4));
6726497c311SBarry Smith   for (i = 0; i < 4; ++i) count[i] = (PetscCount)lbuf[i];
6739566063dSJacob Faibussowitsch   PetscCall(GmshEntitiesCreate(count, &mesh->entities));
674de78e4feSLisandro Dalcin   for (dim = 0; dim < 4; ++dim) {
675730356f6SLisandro Dalcin     for (index = 0; index < count[dim]; ++index) {
6769566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, &eid, 1, NULL, PETSC_ENUM));
6779566063dSJacob Faibussowitsch       if (byteSwap) PetscCall(PetscByteSwap(&eid, PETSC_ENUM, 1));
6789566063dSJacob Faibussowitsch       PetscCall(GmshEntitiesAdd(mesh->entities, (PetscInt)index, dim, eid, &entity));
6799566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, entity->bbox, 6, NULL, PETSC_DOUBLE));
6809566063dSJacob Faibussowitsch       if (byteSwap) PetscCall(PetscByteSwap(entity->bbox, PETSC_DOUBLE, 6));
6816497c311SBarry Smith       PetscCall(PetscViewerRead(viewer, &lnum, 1, NULL, PETSC_LONG));
6826497c311SBarry Smith       if (byteSwap) PetscCall(PetscByteSwap(&lnum, PETSC_LONG, 1));
6836497c311SBarry Smith       PetscCall(PetscIntCast(lnum, &num));
6849566063dSJacob Faibussowitsch       PetscCall(GmshBufferGet(gmsh, num, sizeof(int), &ibuf));
6859566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, ibuf, num, NULL, PETSC_ENUM));
6869566063dSJacob Faibussowitsch       if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, num));
6877d5b9244SMatthew G. Knepley       entity->numTags = numTags = (int)PetscMin(num, GMSH_MAX_TAGS);
688de78e4feSLisandro Dalcin       for (t = 0; t < numTags; ++t) entity->tags[t] = ibuf[t];
689de78e4feSLisandro Dalcin       if (dim == 0) continue;
6906497c311SBarry Smith       PetscCall(PetscViewerRead(viewer, &lnum, 1, NULL, PETSC_LONG));
6916497c311SBarry Smith       if (byteSwap) PetscCall(PetscByteSwap(&lnum, PETSC_LONG, 1));
6926497c311SBarry Smith       PetscCall(GmshBufferGet(gmsh, lnum, sizeof(int), &ibuf));
6936497c311SBarry Smith       PetscCall(PetscIntCast(lnum, &num));
6949566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, ibuf, num, NULL, PETSC_ENUM));
6959566063dSJacob Faibussowitsch       if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, num));
696de78e4feSLisandro Dalcin     }
697de78e4feSLisandro Dalcin   }
6983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
699de78e4feSLisandro Dalcin }
700de78e4feSLisandro Dalcin 
701de78e4feSLisandro Dalcin /*
702de78e4feSLisandro Dalcin $Nodes
703de78e4feSLisandro Dalcin   numEntityBlocks(unsigned long) numNodes(unsigned long)
704de78e4feSLisandro Dalcin   tagEntity(int) dimEntity(int) typeNode(int) numNodes(unsigned long)
705de78e4feSLisandro Dalcin     tag(int) x(double) y(double) z(double)
706de78e4feSLisandro Dalcin     ...
707de78e4feSLisandro Dalcin   ...
708de78e4feSLisandro Dalcin $EndNodes
709de78e4feSLisandro Dalcin */
GmshReadNodes_v40(GmshFile * gmsh,GmshMesh * mesh)710d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes_v40(GmshFile *gmsh, GmshMesh *mesh)
711d71ae5a4SJacob Faibussowitsch {
712698a79b9SLisandro Dalcin   PetscViewer viewer   = gmsh->viewer;
713698a79b9SLisandro Dalcin   PetscBool   byteSwap = gmsh->byteSwap;
7147d5b9244SMatthew G. Knepley   long        block, node, n, t, numEntityBlocks, numTotalNodes, numNodes;
715de78e4feSLisandro Dalcin   int         info[3], nid;
7160598e1a2SLisandro Dalcin   GmshNodes  *nodes;
717de78e4feSLisandro Dalcin 
718de78e4feSLisandro Dalcin   PetscFunctionBegin;
7199566063dSJacob Faibussowitsch   PetscCall(PetscViewerRead(viewer, &numEntityBlocks, 1, NULL, PETSC_LONG));
7209566063dSJacob Faibussowitsch   if (byteSwap) PetscCall(PetscByteSwap(&numEntityBlocks, PETSC_LONG, 1));
7219566063dSJacob Faibussowitsch   PetscCall(PetscViewerRead(viewer, &numTotalNodes, 1, NULL, PETSC_LONG));
7229566063dSJacob Faibussowitsch   if (byteSwap) PetscCall(PetscByteSwap(&numTotalNodes, PETSC_LONG, 1));
7239566063dSJacob Faibussowitsch   PetscCall(GmshNodesCreate(numTotalNodes, &nodes));
7246497c311SBarry Smith   PetscCall(PetscIntCast(numTotalNodes, &mesh->numNodes));
7250598e1a2SLisandro Dalcin   mesh->nodelist = nodes;
7260598e1a2SLisandro Dalcin   for (n = 0, block = 0; block < numEntityBlocks; ++block) {
7279566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, info, 3, NULL, PETSC_ENUM));
7289566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, &numNodes, 1, NULL, PETSC_LONG));
7299566063dSJacob Faibussowitsch     if (byteSwap) PetscCall(PetscByteSwap(&numNodes, PETSC_LONG, 1));
730698a79b9SLisandro Dalcin     if (gmsh->binary) {
731277f51e8SBarry Smith       size_t   nbytes = sizeof(int) + 3 * sizeof(double);
732da81f932SPierre Jolivet       char    *cbuf   = NULL; /* dummy value to prevent warning from compiler about possible uninitialized value */
7336497c311SBarry Smith       PetscInt icnt;
7346497c311SBarry Smith 
7359566063dSJacob Faibussowitsch       PetscCall(GmshBufferGet(gmsh, numNodes, nbytes, &cbuf));
7366497c311SBarry Smith       PetscCall(PetscIntCast(numNodes * nbytes, &icnt));
7376497c311SBarry Smith       PetscCall(PetscViewerRead(viewer, cbuf, icnt, NULL, PETSC_CHAR));
7380598e1a2SLisandro Dalcin       for (node = 0; node < numNodes; ++node, ++n) {
739de78e4feSLisandro Dalcin         char   *cnid = cbuf + node * nbytes, *cxyz = cnid + sizeof(int);
7400598e1a2SLisandro Dalcin         double *xyz = nodes->xyz + n * 3;
7416497c311SBarry Smith 
7429566063dSJacob Faibussowitsch         if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(cnid, PETSC_ENUM, 1));
7439566063dSJacob Faibussowitsch         if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(cxyz, PETSC_DOUBLE, 3));
7449566063dSJacob Faibussowitsch         PetscCall(PetscMemcpy(&nid, cnid, sizeof(int)));
7459566063dSJacob Faibussowitsch         PetscCall(PetscMemcpy(xyz, cxyz, 3 * sizeof(double)));
7469566063dSJacob Faibussowitsch         if (byteSwap) PetscCall(PetscByteSwap(&nid, PETSC_ENUM, 1));
7479566063dSJacob Faibussowitsch         if (byteSwap) PetscCall(PetscByteSwap(xyz, PETSC_DOUBLE, 3));
7480598e1a2SLisandro Dalcin         nodes->id[n] = nid;
7497d5b9244SMatthew G. Knepley         for (t = 0; t < GMSH_MAX_TAGS; ++t) nodes->tag[n * GMSH_MAX_TAGS + t] = -1;
750de78e4feSLisandro Dalcin       }
751de78e4feSLisandro Dalcin     } else {
7520598e1a2SLisandro Dalcin       for (node = 0; node < numNodes; ++node, ++n) {
7530598e1a2SLisandro Dalcin         double *xyz = nodes->xyz + n * 3;
7546497c311SBarry Smith 
7559566063dSJacob Faibussowitsch         PetscCall(PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM));
7569566063dSJacob Faibussowitsch         PetscCall(PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE));
7579566063dSJacob Faibussowitsch         if (byteSwap) PetscCall(PetscByteSwap(&nid, PETSC_ENUM, 1));
7589566063dSJacob Faibussowitsch         if (byteSwap) PetscCall(PetscByteSwap(xyz, PETSC_DOUBLE, 3));
7590598e1a2SLisandro Dalcin         nodes->id[n] = nid;
7607d5b9244SMatthew G. Knepley         for (t = 0; t < GMSH_MAX_TAGS; ++t) nodes->tag[n * GMSH_MAX_TAGS + t] = -1;
761de78e4feSLisandro Dalcin       }
762de78e4feSLisandro Dalcin     }
763de78e4feSLisandro Dalcin   }
7643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
765de78e4feSLisandro Dalcin }
766de78e4feSLisandro Dalcin 
767de78e4feSLisandro Dalcin /*
768de78e4feSLisandro Dalcin $Elements
769de78e4feSLisandro Dalcin   numEntityBlocks(unsigned long) numElements(unsigned long)
770de78e4feSLisandro Dalcin   tagEntity(int) dimEntity(int) typeEle(int) numElements(unsigned long)
771de78e4feSLisandro Dalcin     tag(int) numVert[...](int)
772de78e4feSLisandro Dalcin     ...
773de78e4feSLisandro Dalcin   ...
774de78e4feSLisandro Dalcin $EndElements
775de78e4feSLisandro Dalcin */
GmshReadElements_v40(GmshFile * gmsh,GmshMesh * mesh)776d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements_v40(GmshFile *gmsh, GmshMesh *mesh)
777d71ae5a4SJacob Faibussowitsch {
778698a79b9SLisandro Dalcin   PetscViewer  viewer   = gmsh->viewer;
779698a79b9SLisandro Dalcin   PetscBool    byteSwap = gmsh->byteSwap;
780de78e4feSLisandro Dalcin   long         c, block, numEntityBlocks, numTotalElements, elem, numElements;
781de78e4feSLisandro Dalcin   int          p, info[3], *ibuf = NULL;
7820598e1a2SLisandro Dalcin   int          eid, dim, cellType, numVerts, numNodes, numTags;
783a5ba3d71SLisandro Dalcin   GmshEntity  *entity = NULL;
784de78e4feSLisandro Dalcin   GmshElement *elements;
7856497c311SBarry Smith   PetscInt    *nodeMap = gmsh->nodeMap, icnt;
786de78e4feSLisandro Dalcin 
787de78e4feSLisandro Dalcin   PetscFunctionBegin;
7889566063dSJacob Faibussowitsch   PetscCall(PetscViewerRead(viewer, &numEntityBlocks, 1, NULL, PETSC_LONG));
7899566063dSJacob Faibussowitsch   if (byteSwap) PetscCall(PetscByteSwap(&numEntityBlocks, PETSC_LONG, 1));
7909566063dSJacob Faibussowitsch   PetscCall(PetscViewerRead(viewer, &numTotalElements, 1, NULL, PETSC_LONG));
7919566063dSJacob Faibussowitsch   if (byteSwap) PetscCall(PetscByteSwap(&numTotalElements, PETSC_LONG, 1));
7929566063dSJacob Faibussowitsch   PetscCall(GmshElementsCreate(numTotalElements, &elements));
7936497c311SBarry Smith   PetscCall(PetscIntCast(numTotalElements, &mesh->numElems));
7940598e1a2SLisandro Dalcin   mesh->elements = elements;
795de78e4feSLisandro Dalcin   for (c = 0, block = 0; block < numEntityBlocks; ++block) {
7969566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, info, 3, NULL, PETSC_ENUM));
7979566063dSJacob Faibussowitsch     if (byteSwap) PetscCall(PetscByteSwap(info, PETSC_ENUM, 3));
7989371c9d4SSatish Balay     eid      = info[0];
7999371c9d4SSatish Balay     dim      = info[1];
8009371c9d4SSatish Balay     cellType = info[2];
8019566063dSJacob Faibussowitsch     PetscCall(GmshEntitiesGet(mesh->entities, dim, eid, &entity));
8029566063dSJacob Faibussowitsch     PetscCall(GmshCellTypeCheck(cellType));
8030598e1a2SLisandro Dalcin     numVerts = GmshCellMap[cellType].numVerts;
8040598e1a2SLisandro Dalcin     numNodes = GmshCellMap[cellType].numNodes;
8056497c311SBarry Smith     numTags  = (int)entity->numTags;
8069566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, &numElements, 1, NULL, PETSC_LONG));
8079566063dSJacob Faibussowitsch     if (byteSwap) PetscCall(PetscByteSwap(&numElements, PETSC_LONG, 1));
8089566063dSJacob Faibussowitsch     PetscCall(GmshBufferGet(gmsh, (1 + numNodes) * numElements, sizeof(int), &ibuf));
8096497c311SBarry Smith     PetscCall(PetscIntCast((1 + numNodes) * numElements, &icnt));
8106497c311SBarry Smith     PetscCall(PetscViewerRead(viewer, ibuf, icnt, NULL, PETSC_ENUM));
8119566063dSJacob Faibussowitsch     if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, (1 + numNodes) * numElements));
812de78e4feSLisandro Dalcin     for (elem = 0; elem < numElements; ++elem, ++c) {
813de78e4feSLisandro Dalcin       GmshElement *element = elements + c;
8140598e1a2SLisandro Dalcin       const int   *id = ibuf + elem * (1 + numNodes), *nodes = id + 1;
8150598e1a2SLisandro Dalcin       element->id       = id[0];
816de78e4feSLisandro Dalcin       element->dim      = dim;
817de78e4feSLisandro Dalcin       element->cellType = cellType;
8180598e1a2SLisandro Dalcin       element->numVerts = numVerts;
819de78e4feSLisandro Dalcin       element->numNodes = numNodes;
820de78e4feSLisandro Dalcin       element->numTags  = numTags;
8219566063dSJacob Faibussowitsch       PetscCall(PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes));
8220598e1a2SLisandro Dalcin       for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]];
8230598e1a2SLisandro Dalcin       for (p = 0; p < element->numTags; p++) element->tags[p] = entity->tags[p];
824de78e4feSLisandro Dalcin     }
825de78e4feSLisandro Dalcin   }
8263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
827698a79b9SLisandro Dalcin }
828698a79b9SLisandro Dalcin 
GmshReadPeriodic_v40(GmshFile * gmsh,PetscInt periodicMap[])829d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPeriodic_v40(GmshFile *gmsh, PetscInt periodicMap[])
830d71ae5a4SJacob Faibussowitsch {
831698a79b9SLisandro Dalcin   PetscViewer viewer     = gmsh->viewer;
832698a79b9SLisandro Dalcin   int         fileFormat = gmsh->fileFormat;
833698a79b9SLisandro Dalcin   PetscBool   binary     = gmsh->binary;
834698a79b9SLisandro Dalcin   PetscBool   byteSwap   = gmsh->byteSwap;
835698a79b9SLisandro Dalcin   int         numPeriodic, snum, i;
836698a79b9SLisandro Dalcin   char        line[PETSC_MAX_PATH_LEN];
8370598e1a2SLisandro Dalcin   PetscInt   *nodeMap = gmsh->nodeMap;
838698a79b9SLisandro Dalcin 
839698a79b9SLisandro Dalcin   PetscFunctionBegin;
840698a79b9SLisandro Dalcin   if (fileFormat == 22 || !binary) {
8419566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING));
842698a79b9SLisandro Dalcin     snum = sscanf(line, "%d", &numPeriodic);
84308401ef6SPierre Jolivet     PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
844698a79b9SLisandro Dalcin   } else {
8459566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, &numPeriodic, 1, NULL, PETSC_ENUM));
8469566063dSJacob Faibussowitsch     if (byteSwap) PetscCall(PetscByteSwap(&numPeriodic, PETSC_ENUM, 1));
847698a79b9SLisandro Dalcin   }
848698a79b9SLisandro Dalcin   for (i = 0; i < numPeriodic; i++) {
8499dddd249SSatish Balay     int    ibuf[3], correspondingDim = -1, correspondingTag = -1, primaryTag = -1, correspondingNode, primaryNode;
850698a79b9SLisandro Dalcin     long   j, nNodes;
851698a79b9SLisandro Dalcin     double affine[16];
852698a79b9SLisandro Dalcin 
853698a79b9SLisandro Dalcin     if (fileFormat == 22 || !binary) {
8549566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, line, 3, NULL, PETSC_STRING));
8559dddd249SSatish Balay       snum = sscanf(line, "%d %d %d", &correspondingDim, &correspondingTag, &primaryTag);
85608401ef6SPierre Jolivet       PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
857698a79b9SLisandro Dalcin     } else {
8589566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM));
8599566063dSJacob Faibussowitsch       if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, 3));
8609371c9d4SSatish Balay       correspondingDim = ibuf[0];
8619371c9d4SSatish Balay       correspondingTag = ibuf[1];
8629371c9d4SSatish Balay       primaryTag       = ibuf[2];
863698a79b9SLisandro Dalcin     }
8649371c9d4SSatish Balay     (void)correspondingDim;
8659371c9d4SSatish Balay     (void)correspondingTag;
8669371c9d4SSatish Balay     (void)primaryTag; /* unused */
867698a79b9SLisandro Dalcin 
868698a79b9SLisandro Dalcin     if (fileFormat == 22 || !binary) {
8699566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING));
870698a79b9SLisandro Dalcin       snum = sscanf(line, "%ld", &nNodes);
8714c500f23SPierre Jolivet       if (snum != 1) { /* discard transformation and try again */
8729566063dSJacob Faibussowitsch         PetscCall(PetscViewerRead(viewer, line, -PETSC_MAX_PATH_LEN, NULL, PETSC_STRING));
8739566063dSJacob Faibussowitsch         PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING));
874698a79b9SLisandro Dalcin         snum = sscanf(line, "%ld", &nNodes);
87508401ef6SPierre Jolivet         PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
876698a79b9SLisandro Dalcin       }
877698a79b9SLisandro Dalcin     } else {
8789566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, &nNodes, 1, NULL, PETSC_LONG));
8799566063dSJacob Faibussowitsch       if (byteSwap) PetscCall(PetscByteSwap(&nNodes, PETSC_LONG, 1));
8804c500f23SPierre Jolivet       if (nNodes == -1) { /* discard transformation and try again */
8819566063dSJacob Faibussowitsch         PetscCall(PetscViewerRead(viewer, affine, 16, NULL, PETSC_DOUBLE));
8829566063dSJacob Faibussowitsch         PetscCall(PetscViewerRead(viewer, &nNodes, 1, NULL, PETSC_LONG));
8839566063dSJacob Faibussowitsch         if (byteSwap) PetscCall(PetscByteSwap(&nNodes, PETSC_LONG, 1));
884698a79b9SLisandro Dalcin       }
885698a79b9SLisandro Dalcin     }
886698a79b9SLisandro Dalcin 
887698a79b9SLisandro Dalcin     for (j = 0; j < nNodes; j++) {
888698a79b9SLisandro Dalcin       if (fileFormat == 22 || !binary) {
8899566063dSJacob Faibussowitsch         PetscCall(PetscViewerRead(viewer, line, 2, NULL, PETSC_STRING));
8909dddd249SSatish Balay         snum = sscanf(line, "%d %d", &correspondingNode, &primaryNode);
89108401ef6SPierre Jolivet         PetscCheck(snum == 2, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
892698a79b9SLisandro Dalcin       } else {
8939566063dSJacob Faibussowitsch         PetscCall(PetscViewerRead(viewer, ibuf, 2, NULL, PETSC_ENUM));
8949566063dSJacob Faibussowitsch         if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, 2));
8959371c9d4SSatish Balay         correspondingNode = ibuf[0];
8969371c9d4SSatish Balay         primaryNode       = ibuf[1];
897698a79b9SLisandro Dalcin       }
8989dddd249SSatish Balay       correspondingNode              = (int)nodeMap[correspondingNode];
8999dddd249SSatish Balay       primaryNode                    = (int)nodeMap[primaryNode];
9009dddd249SSatish Balay       periodicMap[correspondingNode] = primaryNode;
901698a79b9SLisandro Dalcin     }
902698a79b9SLisandro Dalcin   }
9033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
904698a79b9SLisandro Dalcin }
905698a79b9SLisandro Dalcin 
9060598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
907698a79b9SLisandro Dalcin $Entities
908698a79b9SLisandro Dalcin   numPoints(size_t) numCurves(size_t)
909698a79b9SLisandro Dalcin     numSurfaces(size_t) numVolumes(size_t)
910698a79b9SLisandro Dalcin   pointTag(int) X(double) Y(double) Z(double)
911698a79b9SLisandro Dalcin     numPhysicalTags(size_t) physicalTag(int) ...
912698a79b9SLisandro Dalcin   ...
913698a79b9SLisandro Dalcin   curveTag(int) minX(double) minY(double) minZ(double)
914698a79b9SLisandro Dalcin     maxX(double) maxY(double) maxZ(double)
915698a79b9SLisandro Dalcin     numPhysicalTags(size_t) physicalTag(int) ...
916698a79b9SLisandro Dalcin     numBoundingPoints(size_t) pointTag(int) ...
917698a79b9SLisandro Dalcin   ...
918698a79b9SLisandro Dalcin   surfaceTag(int) minX(double) minY(double) minZ(double)
919698a79b9SLisandro Dalcin     maxX(double) maxY(double) maxZ(double)
920698a79b9SLisandro Dalcin     numPhysicalTags(size_t) physicalTag(int) ...
921698a79b9SLisandro Dalcin     numBoundingCurves(size_t) curveTag(int) ...
922698a79b9SLisandro Dalcin   ...
923698a79b9SLisandro Dalcin   volumeTag(int) minX(double) minY(double) minZ(double)
924698a79b9SLisandro Dalcin     maxX(double) maxY(double) maxZ(double)
925698a79b9SLisandro Dalcin     numPhysicalTags(size_t) physicalTag(int) ...
926698a79b9SLisandro Dalcin     numBoundngSurfaces(size_t) surfaceTag(int) ...
927698a79b9SLisandro Dalcin   ...
928698a79b9SLisandro Dalcin $EndEntities
929698a79b9SLisandro Dalcin */
GmshReadEntities_v41(GmshFile * gmsh,GmshMesh * mesh)930d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEntities_v41(GmshFile *gmsh, GmshMesh *mesh)
931d71ae5a4SJacob Faibussowitsch {
9326497c311SBarry Smith   PetscCount  count[4], index, numTags;
933698a79b9SLisandro Dalcin   int         dim, eid, *tags = NULL;
934698a79b9SLisandro Dalcin   GmshEntity *entity = NULL;
935698a79b9SLisandro Dalcin 
936698a79b9SLisandro Dalcin   PetscFunctionBegin;
9376497c311SBarry Smith   PetscCall(GmshReadPetscCount(gmsh, count, 4));
9389566063dSJacob Faibussowitsch   PetscCall(GmshEntitiesCreate(count, &mesh->entities));
939698a79b9SLisandro Dalcin   for (dim = 0; dim < 4; ++dim) {
940698a79b9SLisandro Dalcin     for (index = 0; index < count[dim]; ++index) {
9419566063dSJacob Faibussowitsch       PetscCall(GmshReadInt(gmsh, &eid, 1));
9429566063dSJacob Faibussowitsch       PetscCall(GmshEntitiesAdd(mesh->entities, (PetscInt)index, dim, eid, &entity));
9439566063dSJacob Faibussowitsch       PetscCall(GmshReadDouble(gmsh, entity->bbox, (dim == 0) ? 3 : 6));
9446497c311SBarry Smith       PetscCall(GmshReadPetscCount(gmsh, &numTags, 1));
9459566063dSJacob Faibussowitsch       PetscCall(GmshBufferGet(gmsh, numTags, sizeof(int), &tags));
9469566063dSJacob Faibussowitsch       PetscCall(GmshReadInt(gmsh, tags, numTags));
9476497c311SBarry Smith       PetscCheck(numTags <= GMSH_MAX_TAGS, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PETSc currently supports up to %" PetscInt_FMT " tags per entity, not %" PetscCount_FMT, (PetscInt)GMSH_MAX_TAGS, numTags);
9486497c311SBarry Smith       PetscCall(PetscIntCast(numTags, &entity->numTags));
9496497c311SBarry Smith       for (PetscInt i = 0; i < entity->numTags; ++i) entity->tags[i] = tags[i];
950698a79b9SLisandro Dalcin       if (dim == 0) continue;
9516497c311SBarry Smith       PetscCall(GmshReadPetscCount(gmsh, &numTags, 1));
9529566063dSJacob Faibussowitsch       PetscCall(GmshBufferGet(gmsh, numTags, sizeof(int), &tags));
9539566063dSJacob Faibussowitsch       PetscCall(GmshReadInt(gmsh, tags, numTags));
95481a1af93SMatthew G. Knepley       /* Currently, we do not save the ids for the bounding entities */
955698a79b9SLisandro Dalcin     }
956698a79b9SLisandro Dalcin   }
9573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
958698a79b9SLisandro Dalcin }
959698a79b9SLisandro Dalcin 
96033a088b6SMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
961698a79b9SLisandro Dalcin $Nodes
962698a79b9SLisandro Dalcin   numEntityBlocks(size_t) numNodes(size_t)
963698a79b9SLisandro Dalcin     minNodeTag(size_t) maxNodeTag(size_t)
964698a79b9SLisandro Dalcin   entityDim(int) entityTag(int) parametric(int; 0 or 1) numNodesBlock(size_t)
965698a79b9SLisandro Dalcin     nodeTag(size_t)
966698a79b9SLisandro Dalcin     ...
967698a79b9SLisandro Dalcin     x(double) y(double) z(double)
968698a79b9SLisandro Dalcin        < u(double; if parametric and entityDim = 1 or entityDim = 2) >
969698a79b9SLisandro Dalcin        < v(double; if parametric and entityDim = 2) >
970698a79b9SLisandro Dalcin     ...
971698a79b9SLisandro Dalcin   ...
972698a79b9SLisandro Dalcin $EndNodes
973698a79b9SLisandro Dalcin */
GmshReadNodes_v41(GmshFile * gmsh,GmshMesh * mesh)974d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes_v41(GmshFile *gmsh, GmshMesh *mesh)
975d71ae5a4SJacob Faibussowitsch {
97681a1af93SMatthew G. Knepley   int         info[3], dim, eid, parametric;
9776497c311SBarry Smith   PetscCount  sizes[4], numEntityBlocks, numNodes, numNodesBlock = 0;
9786497c311SBarry Smith   PetscInt    numTags;
97981a1af93SMatthew G. Knepley   GmshEntity *entity = NULL;
9800598e1a2SLisandro Dalcin   GmshNodes  *nodes;
981698a79b9SLisandro Dalcin 
982698a79b9SLisandro Dalcin   PetscFunctionBegin;
9836497c311SBarry Smith   PetscCall(GmshReadPetscCount(gmsh, sizes, 4));
9849371c9d4SSatish Balay   numEntityBlocks = sizes[0];
9859371c9d4SSatish Balay   numNodes        = sizes[1];
9869566063dSJacob Faibussowitsch   PetscCall(GmshNodesCreate(numNodes, &nodes));
9876497c311SBarry Smith   PetscCall(PetscIntCast(numNodes, &mesh->numNodes));
9880598e1a2SLisandro Dalcin   mesh->nodelist = nodes;
9896497c311SBarry Smith   if (numEntityBlocks && !mesh->entities) PetscCall(PetscInfo(NULL, "File specifies %" PetscCount_FMT " entity blocks, but was missing the $Entities section\n", numEntityBlocks));
9906497c311SBarry Smith   for (PetscCount block = 0, node = 0; block < numEntityBlocks; ++block, node += numNodesBlock) {
9919566063dSJacob Faibussowitsch     PetscCall(GmshReadInt(gmsh, info, 3));
9929371c9d4SSatish Balay     dim        = info[0];
9939371c9d4SSatish Balay     eid        = info[1];
9949371c9d4SSatish Balay     parametric = info[2];
995e43c9757SMatthew G. Knepley     if (mesh->entities) PetscCall(GmshEntitiesGet(mesh->entities, dim, eid, &entity));
996e43c9757SMatthew G. Knepley     numTags = entity ? entity->numTags : 0;
99781a1af93SMatthew G. Knepley     PetscCheck(!parametric, PETSC_COMM_SELF, PETSC_ERR_SUP, "Parametric coordinates not supported");
9986497c311SBarry Smith     PetscCall(GmshReadPetscCount(gmsh, &numNodesBlock, 1));
9996497c311SBarry Smith     PetscCall(GmshReadPetscInt(gmsh, nodes->id + node, numNodesBlock));
10009566063dSJacob Faibussowitsch     PetscCall(GmshReadDouble(gmsh, nodes->xyz + node * 3, numNodesBlock * 3));
10016497c311SBarry Smith     for (PetscCount n = 0; n < numNodesBlock; ++n) {
10027d5b9244SMatthew G. Knepley       PetscInt *tags = &nodes->tag[node * GMSH_MAX_TAGS];
10037d5b9244SMatthew G. Knepley 
10046497c311SBarry Smith       for (PetscInt t = 0; t < numTags; ++t) tags[n * GMSH_MAX_TAGS + t] = entity->tags[t];
10056497c311SBarry Smith       for (PetscInt t = numTags; t < GMSH_MAX_TAGS; ++t) tags[n * GMSH_MAX_TAGS + t] = -1;
10067d5b9244SMatthew G. Knepley     }
1007698a79b9SLisandro Dalcin   }
10086497c311SBarry Smith   PetscCall(PetscIntCast(sizes[2], &gmsh->nodeStart));
10096497c311SBarry Smith   PetscCall(PetscIntCast(sizes[3] + 1, &gmsh->nodeEnd));
10103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1011698a79b9SLisandro Dalcin }
1012698a79b9SLisandro Dalcin 
101333a088b6SMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
1014698a79b9SLisandro Dalcin $Elements
1015698a79b9SLisandro Dalcin   numEntityBlocks(size_t) numElements(size_t)
1016698a79b9SLisandro Dalcin     minElementTag(size_t) maxElementTag(size_t)
1017698a79b9SLisandro Dalcin   entityDim(int) entityTag(int) elementType(int; see below) numElementsBlock(size_t)
1018698a79b9SLisandro Dalcin     elementTag(size_t) nodeTag(size_t) ...
1019698a79b9SLisandro Dalcin     ...
1020698a79b9SLisandro Dalcin   ...
1021698a79b9SLisandro Dalcin $EndElements
1022698a79b9SLisandro Dalcin */
GmshReadElements_v41(GmshFile * gmsh,GmshMesh * mesh)1023d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements_v41(GmshFile *gmsh, GmshMesh *mesh)
1024d71ae5a4SJacob Faibussowitsch {
10250598e1a2SLisandro Dalcin   int          info[3], eid, dim, cellType;
10266497c311SBarry Smith   PetscCount   sizes[4], numEntityBlocks, numElements, numBlockElements, numVerts, numNodes, numTags, block, elem, c, p;
1027698a79b9SLisandro Dalcin   GmshEntity  *entity = NULL;
1028698a79b9SLisandro Dalcin   GmshElement *elements;
10296497c311SBarry Smith   PetscInt    *nodeMap = gmsh->nodeMap, *ibuf = NULL;
1030698a79b9SLisandro Dalcin 
1031698a79b9SLisandro Dalcin   PetscFunctionBegin;
10326497c311SBarry Smith   PetscCall(GmshReadPetscCount(gmsh, sizes, 4));
10339371c9d4SSatish Balay   numEntityBlocks = sizes[0];
10349371c9d4SSatish Balay   numElements     = sizes[1];
10359566063dSJacob Faibussowitsch   PetscCall(GmshElementsCreate(numElements, &elements));
10366497c311SBarry Smith   PetscCall(PetscIntCast(numElements, &mesh->numElems));
10370598e1a2SLisandro Dalcin   mesh->elements = elements;
10386497c311SBarry Smith   if (numEntityBlocks && !mesh->entities) PetscCall(PetscInfo(NULL, "File specifies %" PetscCount_FMT " entity blocks, but was missing the $Entities section\n", numEntityBlocks));
1039698a79b9SLisandro Dalcin   for (c = 0, block = 0; block < numEntityBlocks; ++block) {
10409566063dSJacob Faibussowitsch     PetscCall(GmshReadInt(gmsh, info, 3));
10419371c9d4SSatish Balay     dim      = info[0];
10429371c9d4SSatish Balay     eid      = info[1];
10439371c9d4SSatish Balay     cellType = info[2];
1044e43c9757SMatthew G. Knepley     if (mesh->entities) PetscCall(GmshEntitiesGet(mesh->entities, dim, eid, &entity));
10459566063dSJacob Faibussowitsch     PetscCall(GmshCellTypeCheck(cellType));
10460598e1a2SLisandro Dalcin     numVerts = GmshCellMap[cellType].numVerts;
10470598e1a2SLisandro Dalcin     numNodes = GmshCellMap[cellType].numNodes;
1048e43c9757SMatthew G. Knepley     numTags  = entity ? entity->numTags : 0;
10496497c311SBarry Smith     PetscCall(GmshReadPetscCount(gmsh, &numBlockElements, 1));
10509566063dSJacob Faibussowitsch     PetscCall(GmshBufferGet(gmsh, (1 + numNodes) * numBlockElements, sizeof(PetscInt), &ibuf));
10516497c311SBarry Smith     PetscCall(GmshReadPetscInt(gmsh, ibuf, (1 + numNodes) * numBlockElements));
1052698a79b9SLisandro Dalcin     for (elem = 0; elem < numBlockElements; ++elem, ++c) {
1053698a79b9SLisandro Dalcin       GmshElement    *element = elements + c;
10540598e1a2SLisandro Dalcin       const PetscInt *id = ibuf + elem * (1 + numNodes), *nodes = id + 1;
10556497c311SBarry Smith 
1056698a79b9SLisandro Dalcin       element->id       = id[0];
1057698a79b9SLisandro Dalcin       element->dim      = dim;
1058698a79b9SLisandro Dalcin       element->cellType = cellType;
10596497c311SBarry Smith       PetscCall(PetscIntCast(numVerts, &element->numVerts));
10606497c311SBarry Smith       PetscCall(PetscIntCast(numNodes, &element->numNodes));
10616497c311SBarry Smith       PetscCall(PetscIntCast(numTags, &element->numTags));
10626497c311SBarry Smith       PetscCall(PetscSegBufferGet(mesh->segbuf, element->numNodes, &element->nodes));
10630598e1a2SLisandro Dalcin       for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]];
10640598e1a2SLisandro Dalcin       for (p = 0; p < element->numTags; p++) element->tags[p] = entity->tags[p];
1065698a79b9SLisandro Dalcin     }
1066698a79b9SLisandro Dalcin   }
10673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1068698a79b9SLisandro Dalcin }
1069698a79b9SLisandro Dalcin 
10700598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
1071698a79b9SLisandro Dalcin $Periodic
1072698a79b9SLisandro Dalcin   numPeriodicLinks(size_t)
10739dddd249SSatish Balay   entityDim(int) entityTag(int) entityTagPrimary(int)
1074698a79b9SLisandro Dalcin   numAffine(size_t) value(double) ...
1075698a79b9SLisandro Dalcin   numCorrespondingNodes(size_t)
10769dddd249SSatish Balay     nodeTag(size_t) nodeTagPrimary(size_t)
1077698a79b9SLisandro Dalcin     ...
1078698a79b9SLisandro Dalcin   ...
1079698a79b9SLisandro Dalcin $EndPeriodic
1080698a79b9SLisandro Dalcin */
GmshReadPeriodic_v41(GmshFile * gmsh,PetscInt periodicMap[])1081d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPeriodic_v41(GmshFile *gmsh, PetscInt periodicMap[])
1082d71ae5a4SJacob Faibussowitsch {
1083698a79b9SLisandro Dalcin   int        info[3];
1084698a79b9SLisandro Dalcin   double     dbuf[16];
10856497c311SBarry Smith   PetscCount numPeriodicLinks, numAffine, numCorrespondingNodes;
10866497c311SBarry Smith   PetscInt  *nodeMap = gmsh->nodeMap, *nodeTags = NULL;
1087698a79b9SLisandro Dalcin 
1088698a79b9SLisandro Dalcin   PetscFunctionBegin;
10896497c311SBarry Smith   PetscCall(GmshReadPetscCount(gmsh, &numPeriodicLinks, 1));
10906497c311SBarry Smith   for (PetscCount link = 0; link < numPeriodicLinks; ++link) {
10919566063dSJacob Faibussowitsch     PetscCall(GmshReadInt(gmsh, info, 3));
10926497c311SBarry Smith     PetscCall(GmshReadPetscCount(gmsh, &numAffine, 1));
10939566063dSJacob Faibussowitsch     PetscCall(GmshReadDouble(gmsh, dbuf, numAffine));
10946497c311SBarry Smith     PetscCall(GmshReadPetscCount(gmsh, &numCorrespondingNodes, 1));
10959566063dSJacob Faibussowitsch     PetscCall(GmshBufferGet(gmsh, numCorrespondingNodes, sizeof(PetscInt), &nodeTags));
10966497c311SBarry Smith     PetscCall(GmshReadPetscInt(gmsh, nodeTags, numCorrespondingNodes * 2));
10976497c311SBarry Smith     for (PetscCount node = 0; node < numCorrespondingNodes; ++node) {
10989dddd249SSatish Balay       PetscInt correspondingNode = nodeMap[nodeTags[node * 2 + 0]];
10999dddd249SSatish Balay       PetscInt primaryNode       = nodeMap[nodeTags[node * 2 + 1]];
11006497c311SBarry Smith 
11019dddd249SSatish Balay       periodicMap[correspondingNode] = primaryNode;
1102698a79b9SLisandro Dalcin     }
1103698a79b9SLisandro Dalcin   }
11043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1105698a79b9SLisandro Dalcin }
1106698a79b9SLisandro Dalcin 
11070598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
1108d6689ca9SLisandro Dalcin $MeshFormat // same as MSH version 2
1109d6689ca9SLisandro Dalcin   version(ASCII double; currently 4.1)
1110d6689ca9SLisandro Dalcin   file-type(ASCII int; 0 for ASCII mode, 1 for binary mode)
1111d6689ca9SLisandro Dalcin   data-size(ASCII int; sizeof(size_t))
1112d6689ca9SLisandro Dalcin   < int with value one; only in binary mode, to detect endianness >
1113d6689ca9SLisandro Dalcin $EndMeshFormat
1114d6689ca9SLisandro Dalcin */
GmshReadMeshFormat(GmshFile * gmsh)1115d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadMeshFormat(GmshFile *gmsh)
1116d71ae5a4SJacob Faibussowitsch {
1117698a79b9SLisandro Dalcin   char  line[PETSC_MAX_PATH_LEN];
1118698a79b9SLisandro Dalcin   int   snum, fileType, fileFormat, dataSize, checkEndian;
1119698a79b9SLisandro Dalcin   float version;
1120698a79b9SLisandro Dalcin 
1121698a79b9SLisandro Dalcin   PetscFunctionBegin;
11229566063dSJacob Faibussowitsch   PetscCall(GmshReadString(gmsh, line, 3));
1123698a79b9SLisandro Dalcin   snum       = sscanf(line, "%f %d %d", &version, &fileType, &dataSize);
1124a8d4e440SJunchao Zhang   fileFormat = (int)roundf(version * 10);
112508401ef6SPierre Jolivet   PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line);
1126a8d4e440SJunchao Zhang   PetscCheck(fileFormat >= 22, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at least 2.2", (double)version);
11271dca8a05SBarry Smith   PetscCheck((int)version != 3, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f not supported", (double)version);
1128a8d4e440SJunchao Zhang   PetscCheck(fileFormat <= 41, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at most 4.1", (double)version);
112908401ef6SPierre Jolivet   PetscCheck(!gmsh->binary || fileType, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Viewer is binary but Gmsh file is ASCII");
113008401ef6SPierre Jolivet   PetscCheck(gmsh->binary || !fileType, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Viewer is ASCII but Gmsh file is binary");
11311dca8a05SBarry Smith   PetscCheck(fileFormat > 40 || dataSize == sizeof(double), PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Data size %d is not valid for a Gmsh file", dataSize);
11321dca8a05SBarry Smith   PetscCheck(fileFormat < 41 || dataSize == sizeof(int) || dataSize == sizeof(PetscInt64), PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Data size %d is not valid for a Gmsh file", dataSize);
1133698a79b9SLisandro Dalcin   gmsh->fileFormat = fileFormat;
1134698a79b9SLisandro Dalcin   gmsh->dataSize   = dataSize;
1135698a79b9SLisandro Dalcin   gmsh->byteSwap   = PETSC_FALSE;
1136698a79b9SLisandro Dalcin   if (gmsh->binary) {
11379566063dSJacob Faibussowitsch     PetscCall(GmshReadInt(gmsh, &checkEndian, 1));
1138698a79b9SLisandro Dalcin     if (checkEndian != 1) {
11399566063dSJacob Faibussowitsch       PetscCall(PetscByteSwap(&checkEndian, PETSC_ENUM, 1));
114008401ef6SPierre Jolivet       PetscCheck(checkEndian == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to detect endianness in Gmsh file header: %s", line);
1141698a79b9SLisandro Dalcin       gmsh->byteSwap = PETSC_TRUE;
1142698a79b9SLisandro Dalcin     }
1143698a79b9SLisandro Dalcin   }
11443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1145698a79b9SLisandro Dalcin }
1146698a79b9SLisandro Dalcin 
11478749820aSMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
11488749820aSMatthew G. Knepley Neper: https://neper.info/ adds this section
11498749820aSMatthew G. Knepley 
11508749820aSMatthew G. Knepley $MeshVersion
11518749820aSMatthew G. Knepley   <major>.<minor>,<patch>
11528749820aSMatthew G. Knepley $EndMeshVersion
11538749820aSMatthew G. Knepley */
GmshReadMeshVersion(GmshFile * gmsh)11548749820aSMatthew G. Knepley static PetscErrorCode GmshReadMeshVersion(GmshFile *gmsh)
11558749820aSMatthew G. Knepley {
11568749820aSMatthew G. Knepley   char line[PETSC_MAX_PATH_LEN];
11578749820aSMatthew G. Knepley   int  snum, major, minor, patch;
11588749820aSMatthew G. Knepley 
11598749820aSMatthew G. Knepley   PetscFunctionBegin;
11608749820aSMatthew G. Knepley   PetscCall(GmshReadString(gmsh, line, 1));
11618749820aSMatthew G. Knepley   snum = sscanf(line, "%d.%d.%d", &major, &minor, &patch);
11628749820aSMatthew G. Knepley   PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line);
11638749820aSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
11648749820aSMatthew G. Knepley }
11658749820aSMatthew G. Knepley 
11668749820aSMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format
11678749820aSMatthew G. Knepley Neper: https://neper.info/ adds this section
11688749820aSMatthew G. Knepley 
11698749820aSMatthew G. Knepley $Domain
11708749820aSMatthew G. Knepley   <shape>
11718749820aSMatthew G. Knepley $EndDomain
11728749820aSMatthew G. Knepley */
GmshReadMeshDomain(GmshFile * gmsh)11738749820aSMatthew G. Knepley static PetscErrorCode GmshReadMeshDomain(GmshFile *gmsh)
11748749820aSMatthew G. Knepley {
11758749820aSMatthew G. Knepley   char line[PETSC_MAX_PATH_LEN];
11768749820aSMatthew G. Knepley 
11778749820aSMatthew G. Knepley   PetscFunctionBegin;
11788749820aSMatthew G. Knepley   PetscCall(GmshReadString(gmsh, line, 1));
11798749820aSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
11808749820aSMatthew G. Knepley }
11818749820aSMatthew G. Knepley 
11821f643af3SLisandro Dalcin /*
11831f643af3SLisandro Dalcin PhysicalNames
11841f643af3SLisandro Dalcin   numPhysicalNames(ASCII int)
11851f643af3SLisandro Dalcin   dimension(ASCII int) physicalTag(ASCII int) "name"(127 characters max)
11861f643af3SLisandro Dalcin   ...
11871f643af3SLisandro Dalcin $EndPhysicalNames
11881f643af3SLisandro Dalcin */
GmshReadPhysicalNames(GmshFile * gmsh,GmshMesh * mesh)1189d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPhysicalNames(GmshFile *gmsh, GmshMesh *mesh)
1190d71ae5a4SJacob Faibussowitsch {
1191bbcf679cSJacob Faibussowitsch   char line[PETSC_MAX_PATH_LEN], name[128 + 2], *p = NULL, *q = NULL, *r = NULL;
1192a45dabc8SMatthew G. Knepley   int  snum, region, dim, tag;
1193698a79b9SLisandro Dalcin 
1194698a79b9SLisandro Dalcin   PetscFunctionBegin;
11959566063dSJacob Faibussowitsch   PetscCall(GmshReadString(gmsh, line, 1));
1196a45dabc8SMatthew G. Knepley   snum             = sscanf(line, "%d", &region);
1197a45dabc8SMatthew G. Knepley   mesh->numRegions = region;
119808401ef6SPierre Jolivet   PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
119990d778b8SLisandro Dalcin   PetscCall(PetscMalloc3(mesh->numRegions, &mesh->regionDims, mesh->numRegions, &mesh->regionTags, mesh->numRegions, &mesh->regionNames));
1200a45dabc8SMatthew G. Knepley   for (region = 0; region < mesh->numRegions; ++region) {
12019566063dSJacob Faibussowitsch     PetscCall(GmshReadString(gmsh, line, 2));
12021f643af3SLisandro Dalcin     snum = sscanf(line, "%d %d", &dim, &tag);
120308401ef6SPierre Jolivet     PetscCheck(snum == 2, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
12049566063dSJacob Faibussowitsch     PetscCall(GmshReadString(gmsh, line, -(PetscInt)sizeof(line)));
12059566063dSJacob Faibussowitsch     PetscCall(PetscStrchr(line, '"', &p));
120628b400f6SJacob Faibussowitsch     PetscCheck(p, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
12079566063dSJacob Faibussowitsch     PetscCall(PetscStrrchr(line, '"', &q));
120808401ef6SPierre Jolivet     PetscCheck(q != p, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file");
12095f5cd6d5SMatthew G. Knepley     PetscCall(PetscStrrchr(line, ':', &r));
12105f5cd6d5SMatthew G. Knepley     if (p != r) q = r;
12119566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(name, p + 1, (size_t)(q - p - 1)));
121290d778b8SLisandro Dalcin     mesh->regionDims[region] = dim;
1213a45dabc8SMatthew G. Knepley     mesh->regionTags[region] = tag;
12149566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &mesh->regionNames[region]));
1215698a79b9SLisandro Dalcin   }
12163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1217de78e4feSLisandro Dalcin }
1218de78e4feSLisandro Dalcin 
GmshReadEntities(GmshFile * gmsh,GmshMesh * mesh)1219d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEntities(GmshFile *gmsh, GmshMesh *mesh)
1220d71ae5a4SJacob Faibussowitsch {
12210598e1a2SLisandro Dalcin   PetscFunctionBegin;
12220598e1a2SLisandro Dalcin   switch (gmsh->fileFormat) {
1223d71ae5a4SJacob Faibussowitsch   case 41:
1224d71ae5a4SJacob Faibussowitsch     PetscCall(GmshReadEntities_v41(gmsh, mesh));
1225d71ae5a4SJacob Faibussowitsch     break;
1226d71ae5a4SJacob Faibussowitsch   default:
1227d71ae5a4SJacob Faibussowitsch     PetscCall(GmshReadEntities_v40(gmsh, mesh));
1228d71ae5a4SJacob Faibussowitsch     break;
122996ca5757SLisandro Dalcin   }
12303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12310598e1a2SLisandro Dalcin }
12320598e1a2SLisandro Dalcin 
GmshReadNodes(GmshFile * gmsh,GmshMesh * mesh)1233d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes(GmshFile *gmsh, GmshMesh *mesh)
1234d71ae5a4SJacob Faibussowitsch {
12350598e1a2SLisandro Dalcin   PetscFunctionBegin;
12360598e1a2SLisandro Dalcin   switch (gmsh->fileFormat) {
1237d71ae5a4SJacob Faibussowitsch   case 41:
1238d71ae5a4SJacob Faibussowitsch     PetscCall(GmshReadNodes_v41(gmsh, mesh));
1239d71ae5a4SJacob Faibussowitsch     break;
1240d71ae5a4SJacob Faibussowitsch   case 40:
1241d71ae5a4SJacob Faibussowitsch     PetscCall(GmshReadNodes_v40(gmsh, mesh));
1242d71ae5a4SJacob Faibussowitsch     break;
1243d71ae5a4SJacob Faibussowitsch   default:
1244d71ae5a4SJacob Faibussowitsch     PetscCall(GmshReadNodes_v22(gmsh, mesh));
1245d71ae5a4SJacob Faibussowitsch     break;
12460598e1a2SLisandro Dalcin   }
12470598e1a2SLisandro Dalcin 
12480598e1a2SLisandro Dalcin   { /* Gmsh v2.2/v4.0 does not provide min/max node tags */
12490598e1a2SLisandro Dalcin     if (mesh->numNodes > 0 && gmsh->nodeEnd >= gmsh->nodeStart) {
12501690c2aeSBarry Smith       PetscInt   tagMin = PETSC_INT_MAX, tagMax = PETSC_INT_MIN, n;
12510598e1a2SLisandro Dalcin       GmshNodes *nodes = mesh->nodelist;
12520598e1a2SLisandro Dalcin       for (n = 0; n < mesh->numNodes; ++n) {
12530598e1a2SLisandro Dalcin         const PetscInt tag = nodes->id[n];
12540598e1a2SLisandro Dalcin         tagMin             = PetscMin(tag, tagMin);
12550598e1a2SLisandro Dalcin         tagMax             = PetscMax(tag, tagMax);
12560598e1a2SLisandro Dalcin       }
12570598e1a2SLisandro Dalcin       gmsh->nodeStart = tagMin;
12580598e1a2SLisandro Dalcin       gmsh->nodeEnd   = tagMax + 1;
12590598e1a2SLisandro Dalcin     }
12600598e1a2SLisandro Dalcin   }
12610598e1a2SLisandro Dalcin 
12620598e1a2SLisandro Dalcin   { /* Support for sparse node tags */
12630598e1a2SLisandro Dalcin     PetscInt   n, t;
12640598e1a2SLisandro Dalcin     GmshNodes *nodes = mesh->nodelist;
12659566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(gmsh->nodeEnd - gmsh->nodeStart, &gmsh->nbuf));
12661690c2aeSBarry Smith     for (t = 0; t < gmsh->nodeEnd - gmsh->nodeStart; ++t) gmsh->nbuf[t] = PETSC_INT_MIN;
12670598e1a2SLisandro Dalcin     gmsh->nodeMap = gmsh->nbuf - gmsh->nodeStart;
12680598e1a2SLisandro Dalcin     for (n = 0; n < mesh->numNodes; ++n) {
12690598e1a2SLisandro Dalcin       const PetscInt tag = nodes->id[n];
127063a3b9bcSJacob Faibussowitsch       PetscCheck(gmsh->nodeMap[tag] < 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Repeated node tag %" PetscInt_FMT, tag);
12710598e1a2SLisandro Dalcin       gmsh->nodeMap[tag] = n;
12720598e1a2SLisandro Dalcin     }
12730598e1a2SLisandro Dalcin   }
12743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12750598e1a2SLisandro Dalcin }
12760598e1a2SLisandro Dalcin 
GmshReadElements(GmshFile * gmsh,GmshMesh * mesh)1277d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements(GmshFile *gmsh, GmshMesh *mesh)
1278d71ae5a4SJacob Faibussowitsch {
12790598e1a2SLisandro Dalcin   PetscFunctionBegin;
12800598e1a2SLisandro Dalcin   switch (gmsh->fileFormat) {
1281d71ae5a4SJacob Faibussowitsch   case 41:
1282d71ae5a4SJacob Faibussowitsch     PetscCall(GmshReadElements_v41(gmsh, mesh));
1283d71ae5a4SJacob Faibussowitsch     break;
1284d71ae5a4SJacob Faibussowitsch   case 40:
1285d71ae5a4SJacob Faibussowitsch     PetscCall(GmshReadElements_v40(gmsh, mesh));
1286d71ae5a4SJacob Faibussowitsch     break;
1287d71ae5a4SJacob Faibussowitsch   default:
1288d71ae5a4SJacob Faibussowitsch     PetscCall(GmshReadElements_v22(gmsh, mesh));
1289d71ae5a4SJacob Faibussowitsch     break;
12900598e1a2SLisandro Dalcin   }
12910598e1a2SLisandro Dalcin 
12920598e1a2SLisandro Dalcin   { /* Reorder elements by codimension and polytope type */
12930598e1a2SLisandro Dalcin     PetscInt     ne       = mesh->numElems;
12940598e1a2SLisandro Dalcin     GmshElement *elements = mesh->elements;
1295066ea43fSLisandro Dalcin     PetscInt     keymap[GMSH_NUM_POLYTOPES], nk = 0;
1296066ea43fSLisandro Dalcin     PetscInt     offset[GMSH_NUM_POLYTOPES + 1], e, k;
12970598e1a2SLisandro Dalcin 
12981690c2aeSBarry Smith     for (k = 0; k < GMSH_NUM_POLYTOPES; ++k) keymap[k] = PETSC_INT_MIN;
12999566063dSJacob Faibussowitsch     PetscCall(PetscMemzero(offset, sizeof(offset)));
13000598e1a2SLisandro Dalcin 
1301066ea43fSLisandro Dalcin     keymap[GMSH_TET] = nk++;
1302066ea43fSLisandro Dalcin     keymap[GMSH_HEX] = nk++;
1303066ea43fSLisandro Dalcin     keymap[GMSH_PRI] = nk++;
1304066ea43fSLisandro Dalcin     keymap[GMSH_PYR] = nk++;
1305066ea43fSLisandro Dalcin     keymap[GMSH_TRI] = nk++;
1306066ea43fSLisandro Dalcin     keymap[GMSH_QUA] = nk++;
1307066ea43fSLisandro Dalcin     keymap[GMSH_SEG] = nk++;
1308066ea43fSLisandro Dalcin     keymap[GMSH_VTX] = nk++;
13090598e1a2SLisandro Dalcin 
13109566063dSJacob Faibussowitsch     PetscCall(GmshElementsCreate(mesh->numElems, &mesh->elements));
13114ad8454bSPierre Jolivet #define key(eid) keymap[GmshCellMap[elements[eid].cellType].polytope]
13120598e1a2SLisandro Dalcin     for (e = 0; e < ne; ++e) offset[1 + key(e)]++;
13130598e1a2SLisandro Dalcin     for (k = 1; k < nk; ++k) offset[k] += offset[k - 1];
13140598e1a2SLisandro Dalcin     for (e = 0; e < ne; ++e) mesh->elements[offset[key(e)]++] = elements[e];
13150598e1a2SLisandro Dalcin #undef key
13169566063dSJacob Faibussowitsch     PetscCall(GmshElementsDestroy(&elements));
1317066ea43fSLisandro Dalcin   }
13180598e1a2SLisandro Dalcin 
1319066ea43fSLisandro Dalcin   { /* Mesh dimension and order */
1320066ea43fSLisandro Dalcin     GmshElement *elem = mesh->numElems ? mesh->elements : NULL;
1321066ea43fSLisandro Dalcin     mesh->dim         = elem ? GmshCellMap[elem->cellType].dim : 0;
1322066ea43fSLisandro Dalcin     mesh->order       = elem ? GmshCellMap[elem->cellType].order : 0;
13230598e1a2SLisandro Dalcin   }
13240598e1a2SLisandro Dalcin 
13250598e1a2SLisandro Dalcin   {
13260598e1a2SLisandro Dalcin     PetscBT  vtx;
13270598e1a2SLisandro Dalcin     PetscInt dim = mesh->dim, e, n, v;
13280598e1a2SLisandro Dalcin 
13299566063dSJacob Faibussowitsch     PetscCall(PetscBTCreate(mesh->numNodes, &vtx));
13300598e1a2SLisandro Dalcin 
13310598e1a2SLisandro Dalcin     /* Compute number of cells and set of vertices */
13320598e1a2SLisandro Dalcin     mesh->numCells = 0;
13330598e1a2SLisandro Dalcin     for (e = 0; e < mesh->numElems; ++e) {
13340598e1a2SLisandro Dalcin       GmshElement *elem = mesh->elements + e;
13350598e1a2SLisandro Dalcin       if (elem->dim == dim && dim > 0) mesh->numCells++;
133648a46eb9SPierre Jolivet       for (v = 0; v < elem->numVerts; v++) PetscCall(PetscBTSet(vtx, elem->nodes[v]));
13370598e1a2SLisandro Dalcin     }
13380598e1a2SLisandro Dalcin 
13390598e1a2SLisandro Dalcin     /* Compute numbering for vertices */
13400598e1a2SLisandro Dalcin     mesh->numVerts = 0;
13419566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(mesh->numNodes, &mesh->vertexMap));
13421690c2aeSBarry Smith     for (n = 0; n < mesh->numNodes; ++n) mesh->vertexMap[n] = PetscBTLookup(vtx, n) ? mesh->numVerts++ : PETSC_INT_MIN;
13430598e1a2SLisandro Dalcin 
13449566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&vtx));
13450598e1a2SLisandro Dalcin   }
13463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13470598e1a2SLisandro Dalcin }
13480598e1a2SLisandro Dalcin 
GmshReadPeriodic(GmshFile * gmsh,GmshMesh * mesh)1349d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPeriodic(GmshFile *gmsh, GmshMesh *mesh)
1350d71ae5a4SJacob Faibussowitsch {
13510598e1a2SLisandro Dalcin   PetscInt n;
13520598e1a2SLisandro Dalcin 
13530598e1a2SLisandro Dalcin   PetscFunctionBegin;
13549566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(mesh->numNodes, &mesh->periodMap));
13550598e1a2SLisandro Dalcin   for (n = 0; n < mesh->numNodes; ++n) mesh->periodMap[n] = n;
13560598e1a2SLisandro Dalcin   switch (gmsh->fileFormat) {
1357d71ae5a4SJacob Faibussowitsch   case 41:
1358d71ae5a4SJacob Faibussowitsch     PetscCall(GmshReadPeriodic_v41(gmsh, mesh->periodMap));
1359d71ae5a4SJacob Faibussowitsch     break;
1360d71ae5a4SJacob Faibussowitsch   default:
1361d71ae5a4SJacob Faibussowitsch     PetscCall(GmshReadPeriodic_v40(gmsh, mesh->periodMap));
1362d71ae5a4SJacob Faibussowitsch     break;
13630598e1a2SLisandro Dalcin   }
13640598e1a2SLisandro Dalcin 
13659dddd249SSatish Balay   /* Find canonical primary nodes */
13660598e1a2SLisandro Dalcin   for (n = 0; n < mesh->numNodes; ++n)
13679371c9d4SSatish Balay     while (mesh->periodMap[n] != mesh->periodMap[mesh->periodMap[n]]) mesh->periodMap[n] = mesh->periodMap[mesh->periodMap[n]];
13680598e1a2SLisandro Dalcin 
13699dddd249SSatish Balay   /* Renumber vertices (filter out correspondings) */
13700598e1a2SLisandro Dalcin   mesh->numVerts = 0;
13710598e1a2SLisandro Dalcin   for (n = 0; n < mesh->numNodes; ++n)
13720598e1a2SLisandro Dalcin     if (mesh->vertexMap[n] >= 0)   /* is vertex */
13739dddd249SSatish Balay       if (mesh->periodMap[n] == n) /* is primary */
13740598e1a2SLisandro Dalcin         mesh->vertexMap[n] = mesh->numVerts++;
13750598e1a2SLisandro Dalcin   for (n = 0; n < mesh->numNodes; ++n)
13760598e1a2SLisandro Dalcin     if (mesh->vertexMap[n] >= 0)   /* is vertex */
13779dddd249SSatish Balay       if (mesh->periodMap[n] != n) /* is corresponding  */
13780598e1a2SLisandro Dalcin         mesh->vertexMap[n] = mesh->vertexMap[mesh->periodMap[n]];
13793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13800598e1a2SLisandro Dalcin }
13810598e1a2SLisandro Dalcin 
1382066ea43fSLisandro Dalcin #define DM_POLYTOPE_VERTEX DM_POLYTOPE_POINT
1383066ea43fSLisandro Dalcin static const DMPolytopeType DMPolytopeMap[] = {
1384066ea43fSLisandro Dalcin   /* GMSH_VTX */ DM_POLYTOPE_VERTEX,
1385066ea43fSLisandro Dalcin   /* GMSH_SEG */ DM_POLYTOPE_SEGMENT,
1386066ea43fSLisandro Dalcin   /* GMSH_TRI */ DM_POLYTOPE_TRIANGLE,
1387066ea43fSLisandro Dalcin   /* GMSH_QUA */ DM_POLYTOPE_QUADRILATERAL,
1388066ea43fSLisandro Dalcin   /* GMSH_TET */ DM_POLYTOPE_TETRAHEDRON,
1389066ea43fSLisandro Dalcin   /* GMSH_HEX */ DM_POLYTOPE_HEXAHEDRON,
1390066ea43fSLisandro Dalcin   /* GMSH_PRI */ DM_POLYTOPE_TRI_PRISM,
13919371c9d4SSatish Balay   /* GMSH_PYR */ DM_POLYTOPE_PYRAMID,       DM_POLYTOPE_UNKNOWN};
13920598e1a2SLisandro Dalcin 
DMPolytopeTypeFromGmsh(PetscInt cellType)1393d71ae5a4SJacob Faibussowitsch static inline DMPolytopeType DMPolytopeTypeFromGmsh(PetscInt cellType)
1394d71ae5a4SJacob Faibussowitsch {
1395066ea43fSLisandro Dalcin   return DMPolytopeMap[GmshCellMap[cellType].polytope];
1396066ea43fSLisandro Dalcin }
1397066ea43fSLisandro Dalcin 
GmshCreateFE(MPI_Comm comm,const char prefix[],PetscBool isSimplex,PetscBool continuity,PetscDTNodeType nodeType,PetscInt dim,PetscInt Nc,PetscInt k,PetscFE * fem)1398d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshCreateFE(MPI_Comm comm, const char prefix[], PetscBool isSimplex, PetscBool continuity, PetscDTNodeType nodeType, PetscInt dim, PetscInt Nc, PetscInt k, PetscFE *fem)
1399d71ae5a4SJacob Faibussowitsch {
1400066ea43fSLisandro Dalcin   DM              K;
1401066ea43fSLisandro Dalcin   PetscSpace      P;
1402066ea43fSLisandro Dalcin   PetscDualSpace  Q;
1403066ea43fSLisandro Dalcin   PetscQuadrature q, fq;
1404066ea43fSLisandro Dalcin   PetscBool       isTensor = isSimplex ? PETSC_FALSE : PETSC_TRUE;
1405066ea43fSLisandro Dalcin   PetscBool       endpoint = PETSC_TRUE;
1406066ea43fSLisandro Dalcin   char            name[32];
1407066ea43fSLisandro Dalcin 
1408066ea43fSLisandro Dalcin   PetscFunctionBegin;
1409066ea43fSLisandro Dalcin   /* Create space */
14109566063dSJacob Faibussowitsch   PetscCall(PetscSpaceCreate(comm, &P));
14119566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSetType(P, PETSCSPACEPOLYNOMIAL));
14129566063dSJacob Faibussowitsch   PetscCall(PetscSpacePolynomialSetTensor(P, isTensor));
14139566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSetNumComponents(P, Nc));
14149566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSetNumVariables(P, dim));
14159566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSetDegree(P, k, PETSC_DETERMINE));
1416066ea43fSLisandro Dalcin   if (prefix) {
14179566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)P, prefix));
14189566063dSJacob Faibussowitsch     PetscCall(PetscSpaceSetFromOptions(P));
14199566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)P, NULL));
14209566063dSJacob Faibussowitsch     PetscCall(PetscSpaceGetDegree(P, &k, NULL));
1421066ea43fSLisandro Dalcin   }
14229566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSetUp(P));
1423066ea43fSLisandro Dalcin   /* Create dual space */
14249566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceCreate(comm, &Q));
14259566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSetType(Q, PETSCDUALSPACELAGRANGE));
14269566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceLagrangeSetTensor(Q, isTensor));
14279566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceLagrangeSetContinuity(Q, continuity));
14289566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceLagrangeSetNodeType(Q, nodeType, endpoint, 0));
14299566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSetNumComponents(Q, Nc));
14309566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSetOrder(Q, k));
14319566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateReferenceCell(PETSC_COMM_SELF, DMPolytopeTypeSimpleShape(dim, isSimplex), &K));
14329566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSetDM(Q, K));
14339566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&K));
1434066ea43fSLisandro Dalcin   if (prefix) {
14359566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)Q, prefix));
14369566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceSetFromOptions(Q));
14379566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)Q, NULL));
1438066ea43fSLisandro Dalcin   }
14399566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSetUp(Q));
1440066ea43fSLisandro Dalcin   /* Create quadrature */
1441066ea43fSLisandro Dalcin   if (isSimplex) {
14429566063dSJacob Faibussowitsch     PetscCall(PetscDTStroudConicalQuadrature(dim, 1, k + 1, -1, +1, &q));
14439566063dSJacob Faibussowitsch     PetscCall(PetscDTStroudConicalQuadrature(dim - 1, 1, k + 1, -1, +1, &fq));
1444066ea43fSLisandro Dalcin   } else {
14459566063dSJacob Faibussowitsch     PetscCall(PetscDTGaussTensorQuadrature(dim, 1, k + 1, -1, +1, &q));
14469566063dSJacob Faibussowitsch     PetscCall(PetscDTGaussTensorQuadrature(dim - 1, 1, k + 1, -1, +1, &fq));
1447066ea43fSLisandro Dalcin   }
1448066ea43fSLisandro Dalcin   /* Create finite element */
14499566063dSJacob Faibussowitsch   PetscCall(PetscFECreate(comm, fem));
14509566063dSJacob Faibussowitsch   PetscCall(PetscFESetType(*fem, PETSCFEBASIC));
14519566063dSJacob Faibussowitsch   PetscCall(PetscFESetNumComponents(*fem, Nc));
14529566063dSJacob Faibussowitsch   PetscCall(PetscFESetBasisSpace(*fem, P));
14539566063dSJacob Faibussowitsch   PetscCall(PetscFESetDualSpace(*fem, Q));
14549566063dSJacob Faibussowitsch   PetscCall(PetscFESetQuadrature(*fem, q));
14559566063dSJacob Faibussowitsch   PetscCall(PetscFESetFaceQuadrature(*fem, fq));
1456066ea43fSLisandro Dalcin   if (prefix) {
14579566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*fem, prefix));
14589566063dSJacob Faibussowitsch     PetscCall(PetscFESetFromOptions(*fem));
14599566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*fem, NULL));
1460066ea43fSLisandro Dalcin   }
14619566063dSJacob Faibussowitsch   PetscCall(PetscFESetUp(*fem));
1462066ea43fSLisandro Dalcin   /* Cleanup */
14639566063dSJacob Faibussowitsch   PetscCall(PetscSpaceDestroy(&P));
14649566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceDestroy(&Q));
14659566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureDestroy(&q));
14669566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureDestroy(&fq));
1467066ea43fSLisandro Dalcin   /* Set finite element name */
146863a3b9bcSJacob Faibussowitsch   PetscCall(PetscSNPrintf(name, sizeof(name), "%s%" PetscInt_FMT, isSimplex ? "P" : "Q", k));
14699566063dSJacob Faibussowitsch   PetscCall(PetscFESetName(*fem, name));
14703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
147196ca5757SLisandro Dalcin }
147296ca5757SLisandro Dalcin 
1473cc4c1da9SBarry Smith /*@
1474a1cb98faSBarry Smith   DMPlexCreateGmshFromFile - Create a `DMPLEX` mesh from a Gmsh file
1475d6689ca9SLisandro Dalcin 
1476a4e35b19SJacob Faibussowitsch   Input Parameters:
1477d6689ca9SLisandro Dalcin + comm        - The MPI communicator
1478d6689ca9SLisandro Dalcin . filename    - Name of the Gmsh file
1479d6689ca9SLisandro Dalcin - interpolate - Create faces and edges in the mesh
1480d6689ca9SLisandro Dalcin 
1481d6689ca9SLisandro Dalcin   Output Parameter:
1482a1cb98faSBarry Smith . dm - The `DM` object representing the mesh
1483d6689ca9SLisandro Dalcin 
1484d6689ca9SLisandro Dalcin   Level: beginner
1485d6689ca9SLisandro Dalcin 
14861cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()`
1487d6689ca9SLisandro Dalcin @*/
DMPlexCreateGmshFromFile(MPI_Comm comm,const char filename[],PetscBool interpolate,DM * dm)1488d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateGmshFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm)
1489d71ae5a4SJacob Faibussowitsch {
1490d6689ca9SLisandro Dalcin   PetscViewer     viewer;
1491d6689ca9SLisandro Dalcin   PetscMPIInt     rank;
1492d6689ca9SLisandro Dalcin   int             fileType;
1493d6689ca9SLisandro Dalcin   PetscViewerType vtype;
1494d6689ca9SLisandro Dalcin 
1495d6689ca9SLisandro Dalcin   PetscFunctionBegin;
14969566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1497d6689ca9SLisandro Dalcin 
1498d6689ca9SLisandro Dalcin   /* Determine Gmsh file type (ASCII or binary) from file header */
1499dd400576SPatrick Sanan   if (rank == 0) {
15000598e1a2SLisandro Dalcin     GmshFile gmsh[1];
1501d6689ca9SLisandro Dalcin     char     line[PETSC_MAX_PATH_LEN];
1502d6689ca9SLisandro Dalcin     int      snum;
1503d6689ca9SLisandro Dalcin     float    version;
1504a8d4e440SJunchao Zhang     int      fileFormat;
1505d6689ca9SLisandro Dalcin 
15069566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(gmsh, 1));
15079566063dSJacob Faibussowitsch     PetscCall(PetscViewerCreate(PETSC_COMM_SELF, &gmsh->viewer));
15089566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetType(gmsh->viewer, PETSCVIEWERASCII));
15099566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileSetMode(gmsh->viewer, FILE_MODE_READ));
15109566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileSetName(gmsh->viewer, filename));
1511d6689ca9SLisandro Dalcin     /* Read only the first two lines of the Gmsh file */
15129566063dSJacob Faibussowitsch     PetscCall(GmshReadSection(gmsh, line));
15139566063dSJacob Faibussowitsch     PetscCall(GmshExpect(gmsh, "$MeshFormat", line));
15149566063dSJacob Faibussowitsch     PetscCall(GmshReadString(gmsh, line, 2));
1515d6689ca9SLisandro Dalcin     snum       = sscanf(line, "%f %d", &version, &fileType);
1516a8d4e440SJunchao Zhang     fileFormat = (int)roundf(version * 10);
151708401ef6SPierre Jolivet     PetscCheck(snum == 2, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line);
1518a8d4e440SJunchao Zhang     PetscCheck(fileFormat >= 22, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at least 2.2", (double)version);
15191dca8a05SBarry Smith     PetscCheck((int)version != 3, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f not supported", (double)version);
1520a8d4e440SJunchao Zhang     PetscCheck(fileFormat <= 41, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at most 4.1", (double)version);
15219566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&gmsh->viewer));
1522d6689ca9SLisandro Dalcin   }
15239566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&fileType, 1, MPI_INT, 0, comm));
1524d6689ca9SLisandro Dalcin   vtype = (fileType == 0) ? PETSCVIEWERASCII : PETSCVIEWERBINARY;
1525d6689ca9SLisandro Dalcin 
1526d6689ca9SLisandro Dalcin   /* Create appropriate viewer and build plex */
15279566063dSJacob Faibussowitsch   PetscCall(PetscViewerCreate(comm, &viewer));
15289566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetType(viewer, vtype));
15299566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
15309566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetName(viewer, filename));
15319566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateGmsh(comm, viewer, interpolate, dm));
15329566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&viewer));
15333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1534d6689ca9SLisandro Dalcin }
1535d6689ca9SLisandro Dalcin 
1536331830f3SMatthew G. Knepley /*@
1537a1cb98faSBarry Smith   DMPlexCreateGmsh - Create a `DMPLEX` mesh from a Gmsh file viewer
1538331830f3SMatthew G. Knepley 
1539d083f849SBarry Smith   Collective
1540331830f3SMatthew G. Knepley 
1541331830f3SMatthew G. Knepley   Input Parameters:
1542331830f3SMatthew G. Knepley + comm        - The MPI communicator
1543a1cb98faSBarry Smith . viewer      - The `PetscViewer` associated with a Gmsh file
1544331830f3SMatthew G. Knepley - interpolate - Create faces and edges in the mesh
1545331830f3SMatthew G. Knepley 
1546331830f3SMatthew G. Knepley   Output Parameter:
1547a1cb98faSBarry Smith . dm - The `DM` object representing the mesh
1548331830f3SMatthew G. Knepley 
1549a1cb98faSBarry Smith   Options Database Keys:
1550df93260fSMatthew G. Knepley + -dm_plex_gmsh_hybrid               - Force triangular prisms to use tensor order
1551df93260fSMatthew G. Knepley . -dm_plex_gmsh_periodic             - Read Gmsh periodic section and construct a periodic Plex
1552df93260fSMatthew G. Knepley . -dm_plex_gmsh_highorder            - Generate high-order coordinates
1553df93260fSMatthew G. Knepley . -dm_plex_gmsh_project              - Project high-order coordinates to a different space, use the prefix dm_plex_gmsh_project_ to define the space
15542b205333SMatthew G. Knepley . -dm_plex_gmsh_use_generic          - Generate generic labels, i.e. Cell Sets, Face Sets, etc.
1555df93260fSMatthew G. Knepley . -dm_plex_gmsh_use_regions          - Generate labels with region names
1556df93260fSMatthew G. Knepley . -dm_plex_gmsh_mark_vertices        - Add vertices to generated labels
15574c375d72SMatthew G. Knepley . -dm_plex_gmsh_mark_vertices_strict - Add vertices included in a region to generated labels
1558df93260fSMatthew G. Knepley . -dm_plex_gmsh_multiple_tags        - Allow multiple tags for default labels
1559df93260fSMatthew G. Knepley - -dm_plex_gmsh_spacedim <d>         - Embedding space dimension, if different from topological dimension
1560df93260fSMatthew G. Knepley 
15611d27aa22SBarry Smith   Level: beginner
15621d27aa22SBarry Smith 
15631d27aa22SBarry Smith   Notes:
15641d27aa22SBarry Smith   The Gmsh file format is described in <http://gmsh.info/doc/texinfo/gmsh.html#MSH-file-format>
1565df93260fSMatthew G. Knepley 
15666497c311SBarry Smith   By default, the "Cell Sets", "Face Sets", and "Vertex Sets" labels are created, and only insert the first tag on a point. By using `-dm_plex_gmsh_multiple_tags`, all tags can be inserted. Alternatively, `-dm_plex_gmsh_use_regions` creates labels based on the region names from the `PhysicalNames` section, and all tags are used, but you can retain the generic labels using `-dm_plex_gmsh_use_generic`.
1567331830f3SMatthew G. Knepley 
15681cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`
1569331830f3SMatthew G. Knepley @*/
DMPlexCreateGmsh(MPI_Comm comm,PetscViewer viewer,PetscBool interpolate,DM * dm)1570d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateGmsh(MPI_Comm comm, PetscViewer viewer, PetscBool interpolate, DM *dm)
1571d71ae5a4SJacob Faibussowitsch {
15720598e1a2SLisandro Dalcin   GmshMesh    *mesh          = NULL;
157311c56cb0SLisandro Dalcin   PetscViewer  parentviewer  = NULL;
15740598e1a2SLisandro Dalcin   PetscBT      periodicVerts = NULL;
1575eae3dc7dSJacob Faibussowitsch   PetscBT     *periodicCells = NULL;
15766858538eSMatthew G. Knepley   DM           cdm, cdmCell = NULL;
15776858538eSMatthew G. Knepley   PetscSection cs, csCell   = NULL;
15786858538eSMatthew G. Knepley   Vec          coordinates, coordinatesCell;
15790444adf6SMatthew G. Knepley   DMLabel      cellSets = NULL, faceSets = NULL, edgeSets = NULL, vertSets = NULL, marker = NULL, *regionSets;
15809db5b827SMatthew G. Knepley   PetscInt     dim = 0, coordDim = -1, order = 0, maxHeight = 0;
15819db5b827SMatthew G. Knepley   PetscInt     numNodes = 0, numElems = 0, numVerts = 0, numCells = 0, vStart, vEnd;
1582066ea43fSLisandro Dalcin   PetscInt     cell, cone[8], e, n, v, d;
15834c375d72SMatthew G. Knepley   PetscBool    usegeneric = PETSC_TRUE, useregions = PETSC_FALSE, markvertices = PETSC_FALSE, markverticesstrict = PETSC_FALSE, multipleTags = PETSC_FALSE;
15842b205333SMatthew G. Knepley   PetscBool    flg, binary, hybrid = interpolate, periodic = PETSC_TRUE;
1585066ea43fSLisandro Dalcin   PetscBool    highOrder = PETSC_TRUE, highOrderSet, project = PETSC_FALSE;
1586066ea43fSLisandro Dalcin   PetscBool    isSimplex = PETSC_FALSE, isHybrid = PETSC_FALSE, hasTetra = PETSC_FALSE;
15870598e1a2SLisandro Dalcin   PetscMPIInt  rank;
1588331830f3SMatthew G. Knepley 
1589331830f3SMatthew G. Knepley   PetscFunctionBegin;
15909566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1591d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)viewer);
1592d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Gmsh options");
1593df93260fSMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_plex_gmsh_hybrid", "Force triangular prisms to use tensor order", "DMPlexCreateGmsh", hybrid, &hybrid, NULL));
15949566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_gmsh_periodic", "Read Gmsh periodic section", "DMPlexCreateGmsh", periodic, &periodic, NULL));
15959566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_gmsh_highorder", "Generate high-order coordinates", "DMPlexCreateGmsh", highOrder, &highOrder, &highOrderSet));
15969566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_gmsh_project", "Project high-order coordinates to a different space", "DMPlexCreateGmsh", project, &project, NULL));
15979566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_gmsh_use_regions", "Generate labels with region names", "DMPlexCreateGmsh", useregions, &useregions, NULL));
15982b205333SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_plex_gmsh_use_generic", "Generate generic labels, i.e. Cell Sets, Face Sets, etc", "DMPlexCreateGmsh", usegeneric, &usegeneric, &flg));
15992b205333SMatthew G. Knepley   if (!flg && useregions) usegeneric = PETSC_FALSE;
16009566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_gmsh_mark_vertices", "Add vertices to generated labels", "DMPlexCreateGmsh", markvertices, &markvertices, NULL));
16014c375d72SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_plex_gmsh_mark_vertices_strict", "Add only directly tagged vertices to generated labels", "DMPlexCreateGmsh", markverticesstrict, &markverticesstrict, NULL));
1602df93260fSMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_plex_gmsh_multiple_tags", "Allow multiple tags for default labels", "DMPlexCreateGmsh", multipleTags, &multipleTags, NULL));
16039566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_gmsh_spacedim", "Embedding space dimension", "DMPlexCreateGmsh", coordDim, &coordDim, NULL, PETSC_DECIDE));
16049db5b827SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_localize_height", "Localize edges and faces in addition to cells", "", maxHeight, &maxHeight, NULL, 0));
1605d0609cedSBarry Smith   PetscOptionsHeadEnd();
1606d0609cedSBarry Smith   PetscOptionsEnd();
16070598e1a2SLisandro Dalcin 
16089566063dSJacob Faibussowitsch   PetscCall(GmshCellInfoSetUp());
160911c56cb0SLisandro Dalcin 
16109566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
16119566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
16129566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CreateGmsh, *dm, NULL, NULL, NULL));
161311c56cb0SLisandro Dalcin 
16149566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &binary));
161511c56cb0SLisandro Dalcin 
161611c56cb0SLisandro Dalcin   /* Binary viewers read on all ranks, get subviewer to read only in rank 0 */
16173b46f529SLisandro Dalcin   if (binary) {
161811c56cb0SLisandro Dalcin     parentviewer = viewer;
16199566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetSubViewer(parentviewer, PETSC_COMM_SELF, &viewer));
162011c56cb0SLisandro Dalcin   }
162111c56cb0SLisandro Dalcin 
1622dd400576SPatrick Sanan   if (rank == 0) {
16230598e1a2SLisandro Dalcin     GmshFile  gmsh[1];
1624698a79b9SLisandro Dalcin     char      line[PETSC_MAX_PATH_LEN];
1625698a79b9SLisandro Dalcin     PetscBool match;
1626331830f3SMatthew G. Knepley 
16279566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(gmsh, 1));
1628698a79b9SLisandro Dalcin     gmsh->viewer = viewer;
1629698a79b9SLisandro Dalcin     gmsh->binary = binary;
1630698a79b9SLisandro Dalcin 
16319566063dSJacob Faibussowitsch     PetscCall(GmshMeshCreate(&mesh));
16320598e1a2SLisandro Dalcin 
1633698a79b9SLisandro Dalcin     /* Read mesh format */
16349566063dSJacob Faibussowitsch     PetscCall(GmshReadSection(gmsh, line));
16359566063dSJacob Faibussowitsch     PetscCall(GmshExpect(gmsh, "$MeshFormat", line));
16369566063dSJacob Faibussowitsch     PetscCall(GmshReadMeshFormat(gmsh));
16379566063dSJacob Faibussowitsch     PetscCall(GmshReadEndSection(gmsh, "$EndMeshFormat", line));
163811c56cb0SLisandro Dalcin 
16398749820aSMatthew G. Knepley     /* OPTIONAL Read mesh version (Neper only) */
16409566063dSJacob Faibussowitsch     PetscCall(GmshReadSection(gmsh, line));
16418749820aSMatthew G. Knepley     PetscCall(GmshMatch(gmsh, "$MeshVersion", line, &match));
16428749820aSMatthew G. Knepley     if (match) {
16438749820aSMatthew G. Knepley       PetscCall(GmshExpect(gmsh, "$MeshVersion", line));
16448749820aSMatthew G. Knepley       PetscCall(GmshReadMeshVersion(gmsh));
16458749820aSMatthew G. Knepley       PetscCall(GmshReadEndSection(gmsh, "$EndMeshVersion", line));
16468749820aSMatthew G. Knepley       /* Initial read for entity section */
16478749820aSMatthew G. Knepley       PetscCall(GmshReadSection(gmsh, line));
16488749820aSMatthew G. Knepley     }
16498749820aSMatthew G. Knepley 
16508749820aSMatthew G. Knepley     /* OPTIONAL Read mesh domain (Neper only) */
16518749820aSMatthew G. Knepley     PetscCall(GmshMatch(gmsh, "$Domain", line, &match));
16528749820aSMatthew G. Knepley     if (match) {
16538749820aSMatthew G. Knepley       PetscCall(GmshExpect(gmsh, "$Domain", line));
16548749820aSMatthew G. Knepley       PetscCall(GmshReadMeshDomain(gmsh));
16558749820aSMatthew G. Knepley       PetscCall(GmshReadEndSection(gmsh, "$EndDomain", line));
16568749820aSMatthew G. Knepley       /* Initial read for entity section */
16578749820aSMatthew G. Knepley       PetscCall(GmshReadSection(gmsh, line));
16588749820aSMatthew G. Knepley     }
16598749820aSMatthew G. Knepley 
16608749820aSMatthew G. Knepley     /* OPTIONAL Read physical names */
16619566063dSJacob Faibussowitsch     PetscCall(GmshMatch(gmsh, "$PhysicalNames", line, &match));
1662dc0ede3bSMatthew G. Knepley     if (match) {
16639566063dSJacob Faibussowitsch       PetscCall(GmshExpect(gmsh, "$PhysicalNames", line));
16649566063dSJacob Faibussowitsch       PetscCall(GmshReadPhysicalNames(gmsh, mesh));
16659566063dSJacob Faibussowitsch       PetscCall(GmshReadEndSection(gmsh, "$EndPhysicalNames", line));
1666698a79b9SLisandro Dalcin       /* Initial read for entity section */
16679566063dSJacob Faibussowitsch       PetscCall(GmshReadSection(gmsh, line));
1668dc0ede3bSMatthew G. Knepley     }
166911c56cb0SLisandro Dalcin 
1670e43c9757SMatthew G. Knepley     /* OPTIONAL Read entities */
1671698a79b9SLisandro Dalcin     if (gmsh->fileFormat >= 40) {
1672e43c9757SMatthew G. Knepley       PetscCall(GmshMatch(gmsh, "$Entities", line, &match));
1673e43c9757SMatthew G. Knepley       if (match) {
16749566063dSJacob Faibussowitsch         PetscCall(GmshExpect(gmsh, "$Entities", line));
16759566063dSJacob Faibussowitsch         PetscCall(GmshReadEntities(gmsh, mesh));
16769566063dSJacob Faibussowitsch         PetscCall(GmshReadEndSection(gmsh, "$EndEntities", line));
1677698a79b9SLisandro Dalcin         /* Initial read for nodes section */
16789566063dSJacob Faibussowitsch         PetscCall(GmshReadSection(gmsh, line));
1679de78e4feSLisandro Dalcin       }
1680e43c9757SMatthew G. Knepley     }
1681de78e4feSLisandro Dalcin 
1682698a79b9SLisandro Dalcin     /* Read nodes */
16839566063dSJacob Faibussowitsch     PetscCall(GmshExpect(gmsh, "$Nodes", line));
16849566063dSJacob Faibussowitsch     PetscCall(GmshReadNodes(gmsh, mesh));
16859566063dSJacob Faibussowitsch     PetscCall(GmshReadEndSection(gmsh, "$EndNodes", line));
168611c56cb0SLisandro Dalcin 
1687698a79b9SLisandro Dalcin     /* Read elements */
16889566063dSJacob Faibussowitsch     PetscCall(GmshReadSection(gmsh, line));
16899566063dSJacob Faibussowitsch     PetscCall(GmshExpect(gmsh, "$Elements", line));
16909566063dSJacob Faibussowitsch     PetscCall(GmshReadElements(gmsh, mesh));
16919566063dSJacob Faibussowitsch     PetscCall(GmshReadEndSection(gmsh, "$EndElements", line));
1692de78e4feSLisandro Dalcin 
16930598e1a2SLisandro Dalcin     /* Read periodic section (OPTIONAL) */
1694698a79b9SLisandro Dalcin     if (periodic) {
16959566063dSJacob Faibussowitsch       PetscCall(GmshReadSection(gmsh, line));
16969566063dSJacob Faibussowitsch       PetscCall(GmshMatch(gmsh, "$Periodic", line, &periodic));
1697ef12879bSLisandro Dalcin     }
1698ef12879bSLisandro Dalcin     if (periodic) {
16999566063dSJacob Faibussowitsch       PetscCall(GmshExpect(gmsh, "$Periodic", line));
17009566063dSJacob Faibussowitsch       PetscCall(GmshReadPeriodic(gmsh, mesh));
17019566063dSJacob Faibussowitsch       PetscCall(GmshReadEndSection(gmsh, "$EndPeriodic", line));
1702698a79b9SLisandro Dalcin     }
1703698a79b9SLisandro Dalcin 
17049566063dSJacob Faibussowitsch     PetscCall(PetscFree(gmsh->wbuf));
17059566063dSJacob Faibussowitsch     PetscCall(PetscFree(gmsh->sbuf));
17069566063dSJacob Faibussowitsch     PetscCall(PetscFree(gmsh->nbuf));
17070598e1a2SLisandro Dalcin 
17080598e1a2SLisandro Dalcin     dim      = mesh->dim;
1709066ea43fSLisandro Dalcin     order    = mesh->order;
17100598e1a2SLisandro Dalcin     numNodes = mesh->numNodes;
17110598e1a2SLisandro Dalcin     numElems = mesh->numElems;
17120598e1a2SLisandro Dalcin     numVerts = mesh->numVerts;
17130598e1a2SLisandro Dalcin     numCells = mesh->numCells;
1714066ea43fSLisandro Dalcin 
1715066ea43fSLisandro Dalcin     {
1716066ea43fSLisandro Dalcin       GmshElement *elemA = mesh->numCells > 0 ? mesh->elements : NULL;
17178e3a54c0SPierre Jolivet       GmshElement *elemB = PetscSafePointerPlusOffset(elemA, mesh->numCells - 1);
1718066ea43fSLisandro Dalcin       int          ptA   = elemA ? GmshCellMap[elemA->cellType].polytope : -1;
1719066ea43fSLisandro Dalcin       int          ptB   = elemB ? GmshCellMap[elemB->cellType].polytope : -1;
1720066ea43fSLisandro Dalcin       isSimplex          = (ptA == GMSH_QUA || ptA == GMSH_HEX) ? PETSC_FALSE : PETSC_TRUE;
1721066ea43fSLisandro Dalcin       isHybrid           = (ptA == ptB) ? PETSC_FALSE : PETSC_TRUE;
1722066ea43fSLisandro Dalcin       hasTetra           = (ptA == GMSH_TET) ? PETSC_TRUE : PETSC_FALSE;
1723066ea43fSLisandro Dalcin     }
1724698a79b9SLisandro Dalcin   }
1725698a79b9SLisandro Dalcin 
172648a46eb9SPierre Jolivet   if (parentviewer) PetscCall(PetscViewerRestoreSubViewer(parentviewer, PETSC_COMM_SELF, &viewer));
1727698a79b9SLisandro Dalcin 
1728066ea43fSLisandro Dalcin   {
1729066ea43fSLisandro Dalcin     int buf[6];
1730698a79b9SLisandro Dalcin 
1731066ea43fSLisandro Dalcin     buf[0] = (int)dim;
1732066ea43fSLisandro Dalcin     buf[1] = (int)order;
1733066ea43fSLisandro Dalcin     buf[2] = periodic;
1734066ea43fSLisandro Dalcin     buf[3] = isSimplex;
1735066ea43fSLisandro Dalcin     buf[4] = isHybrid;
1736066ea43fSLisandro Dalcin     buf[5] = hasTetra;
1737066ea43fSLisandro Dalcin 
17389566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Bcast(buf, 6, MPI_INT, 0, comm));
1739066ea43fSLisandro Dalcin 
1740066ea43fSLisandro Dalcin     dim       = buf[0];
1741066ea43fSLisandro Dalcin     order     = buf[1];
1742066ea43fSLisandro Dalcin     periodic  = buf[2] ? PETSC_TRUE : PETSC_FALSE;
1743066ea43fSLisandro Dalcin     isSimplex = buf[3] ? PETSC_TRUE : PETSC_FALSE;
1744066ea43fSLisandro Dalcin     isHybrid  = buf[4] ? PETSC_TRUE : PETSC_FALSE;
1745066ea43fSLisandro Dalcin     hasTetra  = buf[5] ? PETSC_TRUE : PETSC_FALSE;
1746dea2a3c7SStefano Zampini   }
1747dea2a3c7SStefano Zampini 
1748066ea43fSLisandro Dalcin   if (!highOrderSet) highOrder = (order > 1) ? PETSC_TRUE : PETSC_FALSE;
174908401ef6SPierre Jolivet   PetscCheck(!highOrder || !isHybrid, comm, PETSC_ERR_SUP, "No support for discretization on hybrid meshes yet");
1750066ea43fSLisandro Dalcin 
17510598e1a2SLisandro Dalcin   /* We do not want this label automatically computed, instead we fill it here */
17529566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(*dm, "celltype"));
175311c56cb0SLisandro Dalcin 
1754a4bb7517SMichael Lange   /* Allocate the cell-vertex mesh */
17559566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(*dm, 0, numCells + numVerts));
17560598e1a2SLisandro Dalcin   for (cell = 0; cell < numCells; ++cell) {
17570598e1a2SLisandro Dalcin     GmshElement   *elem  = mesh->elements + cell;
17580598e1a2SLisandro Dalcin     DMPolytopeType ctype = DMPolytopeTypeFromGmsh(elem->cellType);
17590598e1a2SLisandro Dalcin     if (hybrid && hasTetra && ctype == DM_POLYTOPE_TRI_PRISM) ctype = DM_POLYTOPE_TRI_PRISM_TENSOR;
17609566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeSize(*dm, cell, elem->numVerts));
17619566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCellType(*dm, cell, ctype));
1762db397164SMichael Lange   }
176348a46eb9SPierre Jolivet   for (v = numCells; v < numCells + numVerts; ++v) PetscCall(DMPlexSetCellType(*dm, v, DM_POLYTOPE_POINT));
17649566063dSJacob Faibussowitsch   PetscCall(DMSetUp(*dm));
176596ca5757SLisandro Dalcin 
1766a4bb7517SMichael Lange   /* Add cell-vertex connections */
17670598e1a2SLisandro Dalcin   for (cell = 0; cell < numCells; ++cell) {
17680598e1a2SLisandro Dalcin     GmshElement *elem = mesh->elements + cell;
17690598e1a2SLisandro Dalcin     for (v = 0; v < elem->numVerts; ++v) {
17700598e1a2SLisandro Dalcin       const PetscInt nn = elem->nodes[v];
17710598e1a2SLisandro Dalcin       const PetscInt vv = mesh->vertexMap[nn];
17720598e1a2SLisandro Dalcin       cone[v]           = numCells + vv;
1773db397164SMichael Lange     }
17749566063dSJacob Faibussowitsch     PetscCall(DMPlexReorderCell(*dm, cell, cone));
17759566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCone(*dm, cell, cone));
1776a4bb7517SMichael Lange   }
177796ca5757SLisandro Dalcin 
17789566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
17799566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(*dm));
17809566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(*dm));
1781331830f3SMatthew G. Knepley   if (interpolate) {
17825fd9971aSMatthew G. Knepley     DM idm;
1783331830f3SMatthew G. Knepley 
17849566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
17859566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
1786331830f3SMatthew G. Knepley     *dm = idm;
1787331830f3SMatthew G. Knepley   }
17889db5b827SMatthew G. Knepley   PetscCall(DMPlexGetDepthStratum(*dm, 0, &vStart, &vEnd));
1789917266a4SLisandro Dalcin 
1790dd400576SPatrick Sanan   if (rank == 0) {
1791a45dabc8SMatthew G. Knepley     const PetscInt Nr = useregions ? mesh->numRegions : 0;
1792d1a54cefSMatthew G. Knepley 
17939566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(Nr, &regionSets));
17940598e1a2SLisandro Dalcin     for (cell = 0, e = 0; e < numElems; ++e) {
17950598e1a2SLisandro Dalcin       GmshElement *elem = mesh->elements + e;
17966e1dd89aSLawrence Mitchell 
17976e1dd89aSLawrence Mitchell       /* Create cell sets */
17980598e1a2SLisandro Dalcin       if (elem->dim == dim && dim > 0) {
17990598e1a2SLisandro Dalcin         if (elem->numTags > 0) {
1800df93260fSMatthew G. Knepley           PetscInt Nt = elem->numTags, t, r;
1801a45dabc8SMatthew G. Knepley 
1802df93260fSMatthew G. Knepley           for (t = 0; t < Nt; ++t) {
1803df93260fSMatthew G. Knepley             const PetscInt  tag     = elem->tags[t];
18042b205333SMatthew G. Knepley             const PetscBool generic = usegeneric && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE;
1805df93260fSMatthew G. Knepley 
1806df93260fSMatthew G. Knepley             if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &cellSets, "Cell Sets", cell, tag));
1807a45dabc8SMatthew G. Knepley             for (r = 0; r < Nr; ++r) {
1808df93260fSMatthew G. Knepley               if (mesh->regionDims[r] != dim) continue;
18099566063dSJacob Faibussowitsch               if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, &regionSets[r], mesh->regionNames[r], cell, tag));
1810a45dabc8SMatthew G. Knepley             }
18116e1dd89aSLawrence Mitchell           }
1812df93260fSMatthew G. Knepley         }
1813917266a4SLisandro Dalcin         cell++;
18146e1dd89aSLawrence Mitchell       }
18150c070f12SSander Arens 
18160598e1a2SLisandro Dalcin       /* Create face sets */
1817aec57b10SMatthew G. Knepley       if (elem->numTags && interpolate && elem->dim == dim - 1) {
18180598e1a2SLisandro Dalcin         PetscInt        joinSize;
18190598e1a2SLisandro Dalcin         const PetscInt *join = NULL;
18200444adf6SMatthew G. Knepley         PetscInt        Nt   = elem->numTags, pdepth;
1821a45dabc8SMatthew G. Knepley 
18220598e1a2SLisandro Dalcin         /* Find the relevant facet with vertex joins */
18230598e1a2SLisandro Dalcin         for (v = 0; v < elem->numVerts; ++v) {
18240598e1a2SLisandro Dalcin           const PetscInt nn = elem->nodes[v];
18250598e1a2SLisandro Dalcin           const PetscInt vv = mesh->vertexMap[nn];
18260598e1a2SLisandro Dalcin           cone[v]           = vStart + vv;
18270598e1a2SLisandro Dalcin         }
18289566063dSJacob Faibussowitsch         PetscCall(DMPlexGetFullJoin(*dm, elem->numVerts, cone, &joinSize, &join));
182963a3b9bcSJacob Faibussowitsch         PetscCheck(joinSize == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Could not determine Plex facet for Gmsh element %" PetscInt_FMT " (Plex cell %" PetscInt_FMT ")", elem->id, e);
18300444adf6SMatthew G. Knepley         PetscCall(DMPlexGetPointDepth(*dm, join[0], &pdepth));
18310444adf6SMatthew G. Knepley         PetscCheck(pdepth == dim - 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Plex facet %" PetscInt_FMT " for Gmsh element %" PetscInt_FMT " had depth %" PetscInt_FMT " != %" PetscInt_FMT, join[0], elem->id, pdepth, dim - 1);
18320444adf6SMatthew G. Knepley         for (PetscInt t = 0; t < Nt; ++t) {
18335ad74b4fSMatthew G. Knepley           const PetscInt  tag     = elem->tags[t];
18342b205333SMatthew G. Knepley           const PetscBool generic = usegeneric && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE;
18355ad74b4fSMatthew G. Knepley 
1836df93260fSMatthew G. Knepley           if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &faceSets, "Face Sets", join[0], tag));
18370444adf6SMatthew G. Knepley           for (PetscInt r = 0; r < Nr; ++r) {
1838df93260fSMatthew G. Knepley             if (mesh->regionDims[r] != dim - 1) continue;
18399566063dSJacob Faibussowitsch             if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, &regionSets[r], mesh->regionNames[r], join[0], tag));
1840a45dabc8SMatthew G. Knepley           }
18415ad74b4fSMatthew G. Knepley         }
18429566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreJoin(*dm, elem->numVerts, cone, &joinSize, &join));
18430598e1a2SLisandro Dalcin       }
18440598e1a2SLisandro Dalcin 
1845aec57b10SMatthew G. Knepley       /* Create edge sets */
1846aec57b10SMatthew G. Knepley       if (elem->numTags && interpolate && dim > 2 && elem->dim == 1) {
1847aec57b10SMatthew G. Knepley         PetscInt        joinSize;
1848aec57b10SMatthew G. Knepley         const PetscInt *join = NULL;
1849aec57b10SMatthew G. Knepley         PetscInt        Nt   = elem->numTags, t, r;
1850aec57b10SMatthew G. Knepley 
1851aec57b10SMatthew G. Knepley         /* Find the relevant edge with vertex joins */
1852aec57b10SMatthew G. Knepley         for (v = 0; v < elem->numVerts; ++v) {
1853aec57b10SMatthew G. Knepley           const PetscInt nn = elem->nodes[v];
1854aec57b10SMatthew G. Knepley           const PetscInt vv = mesh->vertexMap[nn];
1855aec57b10SMatthew G. Knepley           cone[v]           = vStart + vv;
1856aec57b10SMatthew G. Knepley         }
1857aec57b10SMatthew G. Knepley         PetscCall(DMPlexGetJoin(*dm, elem->numVerts, cone, &joinSize, &join));
1858aec57b10SMatthew G. Knepley         PetscCheck(joinSize == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Could not determine Plex edge for Gmsh element %" PetscInt_FMT " (Plex cell %" PetscInt_FMT ")", elem->id, e);
1859aec57b10SMatthew G. Knepley         for (t = 0; t < Nt; ++t) {
1860aec57b10SMatthew G. Knepley           const PetscInt  tag     = elem->tags[t];
18612b205333SMatthew G. Knepley           const PetscBool generic = usegeneric && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE;
1862aec57b10SMatthew G. Knepley 
18630444adf6SMatthew G. Knepley           if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &edgeSets, "Edge Sets", join[0], tag));
1864aec57b10SMatthew G. Knepley           for (r = 0; r < Nr; ++r) {
1865aec57b10SMatthew G. Knepley             if (mesh->regionDims[r] != 1) continue;
1866aec57b10SMatthew G. Knepley             if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, &regionSets[r], mesh->regionNames[r], join[0], tag));
1867aec57b10SMatthew G. Knepley           }
1868aec57b10SMatthew G. Knepley         }
1869aec57b10SMatthew G. Knepley         PetscCall(DMPlexRestoreJoin(*dm, elem->numVerts, cone, &joinSize, &join));
1870aec57b10SMatthew G. Knepley       }
1871aec57b10SMatthew G. Knepley 
18720c070f12SSander Arens       /* Create vertex sets */
18734c375d72SMatthew G. Knepley       if (elem->numTags && elem->dim == 0 && (markverticesstrict || markvertices)) {
18740598e1a2SLisandro Dalcin         const PetscInt nn = elem->nodes[0];
18750598e1a2SLisandro Dalcin         const PetscInt vv = mesh->vertexMap[nn];
1876bb3f7942SBrad Aagaard         PetscInt       Nt = elem->numTags;
1877bb3f7942SBrad Aagaard 
1878bb3f7942SBrad Aagaard         for (PetscInt t = 0; t < Nt; ++t) {
1879bb3f7942SBrad Aagaard           const PetscInt tag = elem->tags[t];
1880a45dabc8SMatthew G. Knepley 
18818a3d9825SMatthew G. Knepley           if (vv < 0) continue;
18822b205333SMatthew G. Knepley           if (usegeneric) PetscCall(DMSetLabelValue_Fast(*dm, &vertSets, "Vertex Sets", vStart + vv, tag));
1883bb3f7942SBrad Aagaard           for (PetscInt r = 0; r < Nr; ++r) {
1884df93260fSMatthew G. Knepley             if (mesh->regionDims[r] != 0) continue;
18859566063dSJacob Faibussowitsch             if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, &regionSets[r], mesh->regionNames[r], vStart + vv, tag));
188681a1af93SMatthew G. Knepley           }
188781a1af93SMatthew G. Knepley         }
188881a1af93SMatthew G. Knepley       }
1889bb3f7942SBrad Aagaard     }
189081a1af93SMatthew G. Knepley     if (markvertices) {
189181a1af93SMatthew G. Knepley       for (v = 0; v < numNodes; ++v) {
189281a1af93SMatthew G. Knepley         const PetscInt  vv   = mesh->vertexMap[v];
18937d5b9244SMatthew G. Knepley         const PetscInt *tags = &mesh->nodelist->tag[v * GMSH_MAX_TAGS];
18947d5b9244SMatthew G. Knepley         PetscInt        r, t;
189581a1af93SMatthew G. Knepley 
18968a3d9825SMatthew G. Knepley         if (vv < 0) continue;
18977d5b9244SMatthew G. Knepley         for (t = 0; t < GMSH_MAX_TAGS; ++t) {
18987d5b9244SMatthew G. Knepley           const PetscInt  tag     = tags[t];
18992b205333SMatthew G. Knepley           const PetscBool generic = usegeneric && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE;
19007d5b9244SMatthew G. Knepley 
19017d5b9244SMatthew G. Knepley           if (tag == -1) continue;
1902df93260fSMatthew G. Knepley           if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &vertSets, "Vertex Sets", vStart + vv, tag));
1903a45dabc8SMatthew G. Knepley           for (r = 0; r < Nr; ++r) {
19049566063dSJacob Faibussowitsch             if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, &regionSets[r], mesh->regionNames[r], vStart + vv, tag));
19050598e1a2SLisandro Dalcin           }
19060598e1a2SLisandro Dalcin         }
19070598e1a2SLisandro Dalcin       }
19080598e1a2SLisandro Dalcin     }
19099566063dSJacob Faibussowitsch     PetscCall(PetscFree(regionSets));
1910a45dabc8SMatthew G. Knepley   }
19110598e1a2SLisandro Dalcin 
19120444adf6SMatthew G. Knepley   { /* Create Cell/Face/Edge/Vertex Sets labels at all processes */
19139371c9d4SSatish Balay     enum {
19140444adf6SMatthew G. Knepley       n = 5
19159371c9d4SSatish Balay     };
19167dd454faSLisandro Dalcin     PetscBool flag[n];
19177dd454faSLisandro Dalcin 
19187dd454faSLisandro Dalcin     flag[0] = cellSets ? PETSC_TRUE : PETSC_FALSE;
19197dd454faSLisandro Dalcin     flag[1] = faceSets ? PETSC_TRUE : PETSC_FALSE;
19200444adf6SMatthew G. Knepley     flag[2] = edgeSets ? PETSC_TRUE : PETSC_FALSE;
19210444adf6SMatthew G. Knepley     flag[3] = vertSets ? PETSC_TRUE : PETSC_FALSE;
19220444adf6SMatthew G. Knepley     flag[4] = marker ? PETSC_TRUE : PETSC_FALSE;
1923*5440e5dcSBarry Smith     PetscCallMPI(MPI_Bcast(flag, n, MPI_C_BOOL, 0, comm));
19249566063dSJacob Faibussowitsch     if (flag[0]) PetscCall(DMCreateLabel(*dm, "Cell Sets"));
19259566063dSJacob Faibussowitsch     if (flag[1]) PetscCall(DMCreateLabel(*dm, "Face Sets"));
19260444adf6SMatthew G. Knepley     if (flag[2]) PetscCall(DMCreateLabel(*dm, "Edge Sets"));
19270444adf6SMatthew G. Knepley     if (flag[3]) PetscCall(DMCreateLabel(*dm, "Vertex Sets"));
19280444adf6SMatthew G. Knepley     if (flag[4]) PetscCall(DMCreateLabel(*dm, "marker"));
19297dd454faSLisandro Dalcin   }
19307dd454faSLisandro Dalcin 
19310598e1a2SLisandro Dalcin   if (periodic) {
19329566063dSJacob Faibussowitsch     PetscCall(PetscBTCreate(numVerts, &periodicVerts));
19330598e1a2SLisandro Dalcin     for (n = 0; n < numNodes; ++n) {
19340598e1a2SLisandro Dalcin       if (mesh->vertexMap[n] >= 0) {
19350598e1a2SLisandro Dalcin         if (PetscUnlikely(mesh->periodMap[n] != n)) {
19360598e1a2SLisandro Dalcin           PetscInt m = mesh->periodMap[n];
19379566063dSJacob Faibussowitsch           PetscCall(PetscBTSet(periodicVerts, mesh->vertexMap[n]));
19389566063dSJacob Faibussowitsch           PetscCall(PetscBTSet(periodicVerts, mesh->vertexMap[m]));
19390598e1a2SLisandro Dalcin         }
19400598e1a2SLisandro Dalcin       }
19410598e1a2SLisandro Dalcin     }
19429db5b827SMatthew G. Knepley     PetscCall(DMGetCoordinateDM(*dm, &cdm));
1943eae3dc7dSJacob Faibussowitsch     PetscCall(PetscMalloc1(maxHeight + 1, &periodicCells));
19449db5b827SMatthew G. Knepley     for (PetscInt h = 0; h <= maxHeight; ++h) {
19459db5b827SMatthew G. Knepley       PetscInt pStart, pEnd;
19469db5b827SMatthew G. Knepley 
19479db5b827SMatthew G. Knepley       PetscCall(DMPlexGetHeightStratum(*dm, h, &pStart, &pEnd));
19489db5b827SMatthew G. Knepley       PetscCall(PetscBTCreate(pEnd - pStart, &periodicCells[h]));
19499db5b827SMatthew G. Knepley       for (PetscInt p = pStart; p < pEnd; ++p) {
19509db5b827SMatthew G. Knepley         PetscInt *closure = NULL;
19519db5b827SMatthew G. Knepley         PetscInt  Ncl;
19529db5b827SMatthew G. Knepley 
19539db5b827SMatthew G. Knepley         PetscCall(DMPlexGetTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure));
19549db5b827SMatthew G. Knepley         for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) {
19559db5b827SMatthew G. Knepley           if (closure[cl] >= vStart && closure[cl] < vEnd) {
19569db5b827SMatthew G. Knepley             if (PetscUnlikely(PetscBTLookup(periodicVerts, closure[cl] - vStart))) {
19579db5b827SMatthew G. Knepley               PetscCall(PetscBTSet(periodicCells[h], p - pStart));
19589371c9d4SSatish Balay               break;
19590c070f12SSander Arens             }
19600c070f12SSander Arens           }
19610c070f12SSander Arens         }
19629db5b827SMatthew G. Knepley         PetscCall(DMPlexRestoreTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure));
19639db5b827SMatthew G. Knepley       }
19649db5b827SMatthew G. Knepley     }
196516ad7e67SMichael Lange   }
196616ad7e67SMichael Lange 
1967066ea43fSLisandro Dalcin   /* Setup coordinate DM */
19680598e1a2SLisandro Dalcin   if (coordDim < 0) coordDim = dim;
19699566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(*dm, coordDim));
19709566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(*dm, &cdm));
1971066ea43fSLisandro Dalcin   if (highOrder) {
1972066ea43fSLisandro Dalcin     PetscFE         fe;
1973066ea43fSLisandro Dalcin     PetscBool       continuity = periodic ? PETSC_FALSE : PETSC_TRUE;
1974066ea43fSLisandro Dalcin     PetscDTNodeType nodeType   = PETSCDTNODES_EQUISPACED;
1975066ea43fSLisandro Dalcin 
1976066ea43fSLisandro Dalcin     if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */
1977066ea43fSLisandro Dalcin 
19789566063dSJacob Faibussowitsch     PetscCall(GmshCreateFE(comm, NULL, isSimplex, continuity, nodeType, dim, coordDim, order, &fe));
19799566063dSJacob Faibussowitsch     PetscCall(PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_fe_view"));
19809566063dSJacob Faibussowitsch     PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)fe));
19819566063dSJacob Faibussowitsch     PetscCall(PetscFEDestroy(&fe));
19829566063dSJacob Faibussowitsch     PetscCall(DMCreateDS(cdm));
1983066ea43fSLisandro Dalcin   }
19846858538eSMatthew G. Knepley   if (periodic) {
19856858538eSMatthew G. Knepley     PetscCall(DMClone(cdm, &cdmCell));
19866858538eSMatthew G. Knepley     PetscCall(DMSetCellCoordinateDM(*dm, cdmCell));
19876858538eSMatthew G. Knepley   }
1988066ea43fSLisandro Dalcin 
1989066ea43fSLisandro Dalcin   /* Create coordinates */
1990066ea43fSLisandro Dalcin   if (highOrder) {
1991066ea43fSLisandro Dalcin     PetscInt     maxDof = GmshNumNodes_HEX(order) * coordDim;
1992066ea43fSLisandro Dalcin     double      *coords = mesh ? mesh->nodelist->xyz : NULL;
1993066ea43fSLisandro Dalcin     PetscSection section;
1994066ea43fSLisandro Dalcin     PetscScalar *cellCoords;
1995066ea43fSLisandro Dalcin 
19969566063dSJacob Faibussowitsch     PetscCall(DMSetLocalSection(cdm, NULL));
19976858538eSMatthew G. Knepley     PetscCall(DMGetLocalSection(cdm, &cs));
19986858538eSMatthew G. Knepley     PetscCall(PetscSectionClone(cs, &section));
19999566063dSJacob Faibussowitsch     PetscCall(DMPlexSetClosurePermutationTensor(cdm, 0, section)); /* XXX Implement DMPlexSetClosurePermutationLexicographic() */
2000066ea43fSLisandro Dalcin 
20019566063dSJacob Faibussowitsch     PetscCall(DMCreateLocalVector(cdm, &coordinates));
20029566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(maxDof, &cellCoords));
2003066ea43fSLisandro Dalcin     for (cell = 0; cell < numCells; ++cell) {
2004066ea43fSLisandro Dalcin       GmshElement *elem     = mesh->elements + cell;
2005066ea43fSLisandro Dalcin       const int   *lexorder = GmshCellMap[elem->cellType].lexorder();
2006b9bf55e5SMatthew G. Knepley       int          s        = 0;
2007066ea43fSLisandro Dalcin       for (n = 0; n < elem->numNodes; ++n) {
2008b9bf55e5SMatthew G. Knepley         while (lexorder[n + s] < 0) ++s;
2009b9bf55e5SMatthew G. Knepley         const PetscInt node = elem->nodes[lexorder[n + s]];
2010b9bf55e5SMatthew G. Knepley         for (d = 0; d < coordDim; ++d) cellCoords[(n + s) * coordDim + d] = (PetscReal)coords[node * 3 + d];
2011b9bf55e5SMatthew G. Knepley       }
2012b9bf55e5SMatthew G. Knepley       if (s) {
2013b9bf55e5SMatthew G. Knepley         /* For the coordinate mapping we weight vertices by -1/4 and edges by 1/2, which we get from Q_2 interpolation */
2014b9bf55e5SMatthew G. Knepley         PetscReal quaCenterWeights[9] = {-0.25, 0.5, -0.25, 0.5, 0.0, 0.5, -0.25, 0.5, -0.25};
2015b9bf55e5SMatthew G. Knepley         /* For the coordinate mapping we weight vertices by -1/4 and edges by 1/2, which we get from Q_2 interpolation */
20169371c9d4SSatish Balay         PetscReal   hexBottomWeights[27] = {-0.25, 0.5, -0.25, 0.5, 0.0, 0.5, -0.25, 0.5, -0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
20179371c9d4SSatish Balay         PetscReal   hexFrontWeights[27]  = {-0.25, 0.5, -0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.25, 0.5, -0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
20189371c9d4SSatish Balay         PetscReal   hexLeftWeights[27]   = {-0.25, 0.0, 0.0, 0.5, 0.0, 0.0, -0.25, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, -0.25, 0.0, 0.0, 0.5, 0.0, 0.0, -0.25, 0.0, 0.0};
20199371c9d4SSatish Balay         PetscReal   hexRightWeights[27]  = {0.0, 0.0, -0.25, 0.0, 0.0, 0.5, 0.0, 0.0, -0.25, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, -0.25, 0.0, 0.0, 0.5, 0.0, 0.0, -0.25};
20209371c9d4SSatish Balay         PetscReal   hexBackWeights[27]   = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.25, 0.5, -0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.25, 0.5, -0.25};
20219371c9d4SSatish Balay         PetscReal   hexTopWeights[27]    = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.25, 0.5, -0.25, 0.5, 0.0, 0.5, -0.25, 0.5, -0.25};
20229371c9d4SSatish Balay         PetscReal   hexCenterWeights[27] = {-0.25, 0.25, -0.25, 0.25, 0.0, 0.25, -0.25, 0.25, -0.25, 0.25, 0.0, 0.25, 0.0, 0.0, 0.0, 0.25, 0.0, 0.25, -0.25, 0.25, -0.25, 0.25, 0.0, 0.25, -0.25, 0.25, -0.25};
2023b9bf55e5SMatthew G. Knepley         PetscReal  *sdWeights2[9]        = {NULL, NULL, NULL, NULL, quaCenterWeights, NULL, NULL, NULL, NULL};
20249371c9d4SSatish Balay         PetscReal  *sdWeights3[27]       = {NULL, NULL, NULL, NULL, hexBottomWeights, NULL, NULL, NULL, NULL, NULL, hexFrontWeights, NULL, hexLeftWeights, hexCenterWeights, hexRightWeights, NULL, hexBackWeights, NULL,
2025b9bf55e5SMatthew G. Knepley                                             NULL, NULL, NULL, NULL, hexTopWeights,    NULL, NULL, NULL, NULL};
2026b9bf55e5SMatthew G. Knepley         PetscReal **sdWeights[4]         = {NULL, NULL, sdWeights2, sdWeights3};
2027b9bf55e5SMatthew G. Knepley 
2028b9bf55e5SMatthew G. Knepley         /* Missing entries in serendipity cell, only works for 8-node quad and 20-node hex */
2029b9bf55e5SMatthew G. Knepley         for (n = 0; n < elem->numNodes + s; ++n) {
2030b9bf55e5SMatthew G. Knepley           if (lexorder[n] >= 0) continue;
2031b9bf55e5SMatthew G. Knepley           for (d = 0; d < coordDim; ++d) cellCoords[n * coordDim + d] = 0.0;
2032b9bf55e5SMatthew G. Knepley           for (int bn = 0; bn < elem->numNodes + s; ++bn) {
2033b9bf55e5SMatthew G. Knepley             if (lexorder[bn] < 0) continue;
2034b9bf55e5SMatthew G. Knepley             const PetscReal *weights = sdWeights[coordDim][n];
2035b9bf55e5SMatthew G. Knepley             const PetscInt   bnode   = elem->nodes[lexorder[bn]];
2036b9bf55e5SMatthew G. Knepley             for (d = 0; d < coordDim; ++d) cellCoords[n * coordDim + d] += weights[bn] * (PetscReal)coords[bnode * 3 + d];
2037b9bf55e5SMatthew G. Knepley           }
2038b9bf55e5SMatthew G. Knepley         }
2039066ea43fSLisandro Dalcin       }
20409566063dSJacob Faibussowitsch       PetscCall(DMPlexVecSetClosure(cdm, section, coordinates, cell, cellCoords, INSERT_VALUES));
2041066ea43fSLisandro Dalcin     }
20429566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&section));
20439566063dSJacob Faibussowitsch     PetscCall(PetscFree(cellCoords));
2044066ea43fSLisandro Dalcin   } else {
2045066ea43fSLisandro Dalcin     PetscInt    *nodeMap;
2046066ea43fSLisandro Dalcin     double      *coords = mesh ? mesh->nodelist->xyz : NULL;
2047066ea43fSLisandro Dalcin     PetscScalar *pointCoords;
2048066ea43fSLisandro Dalcin 
20496858538eSMatthew G. Knepley     PetscCall(DMGetCoordinateSection(*dm, &cs));
20506858538eSMatthew G. Knepley     PetscCall(PetscSectionSetNumFields(cs, 1));
20516858538eSMatthew G. Knepley     PetscCall(PetscSectionSetFieldComponents(cs, 0, coordDim));
20526858538eSMatthew G. Knepley     PetscCall(PetscSectionSetChart(cs, numCells, numCells + numVerts));
20536858538eSMatthew G. Knepley     for (v = numCells; v < numCells + numVerts; ++v) {
20546858538eSMatthew G. Knepley       PetscCall(PetscSectionSetDof(cs, v, coordDim));
20556858538eSMatthew G. Knepley       PetscCall(PetscSectionSetFieldDof(cs, v, 0, coordDim));
2056f45c9589SStefano Zampini     }
20576858538eSMatthew G. Knepley     PetscCall(PetscSectionSetUp(cs));
20586858538eSMatthew G. Knepley 
20596858538eSMatthew G. Knepley     /* We need to localize coordinates on cells */
20600598e1a2SLisandro Dalcin     if (periodic) {
20611690c2aeSBarry Smith       PetscInt newStart = PETSC_INT_MAX, newEnd = -1, pStart, pEnd;
20629db5b827SMatthew G. Knepley 
20636858538eSMatthew G. Knepley       PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)cdmCell), &csCell));
20646858538eSMatthew G. Knepley       PetscCall(PetscSectionSetNumFields(csCell, 1));
20656858538eSMatthew G. Knepley       PetscCall(PetscSectionSetFieldComponents(csCell, 0, coordDim));
20669db5b827SMatthew G. Knepley       for (PetscInt h = 0; h <= maxHeight; h++) {
20679db5b827SMatthew G. Knepley         PetscCall(DMPlexGetHeightStratum(cdmCell, h, &pStart, &pEnd));
20689db5b827SMatthew G. Knepley         newStart = PetscMin(newStart, pStart);
20699db5b827SMatthew G. Knepley         newEnd   = PetscMax(newEnd, pEnd);
20709db5b827SMatthew G. Knepley       }
20719db5b827SMatthew G. Knepley       PetscCall(PetscSectionSetChart(csCell, newStart, newEnd));
20729db5b827SMatthew G. Knepley       for (PetscInt h = 0; h <= maxHeight; h++) {
20739db5b827SMatthew G. Knepley         PetscCall(DMPlexGetHeightStratum(cdmCell, h, &pStart, &pEnd));
20749db5b827SMatthew G. Knepley         for (PetscInt p = pStart; p < pEnd; ++p) {
20759db5b827SMatthew G. Knepley           PetscInt *closure = NULL;
20769db5b827SMatthew G. Knepley           PetscInt  Ncl, Nv = 0;
20776858538eSMatthew G. Knepley 
20789db5b827SMatthew G. Knepley           if (PetscUnlikely(PetscBTLookup(periodicCells[h], p - pStart))) {
20799db5b827SMatthew G. Knepley             PetscCall(DMPlexGetTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure));
20809db5b827SMatthew G. Knepley             for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) {
20819db5b827SMatthew G. Knepley               if (closure[cl] >= vStart && closure[cl] < vEnd) ++Nv;
20829db5b827SMatthew G. Knepley             }
20839db5b827SMatthew G. Knepley             PetscCall(DMPlexRestoreTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure));
20849db5b827SMatthew G. Knepley             PetscCall(PetscSectionSetDof(csCell, p, Nv * coordDim));
20859db5b827SMatthew G. Knepley             PetscCall(PetscSectionSetFieldDof(csCell, p, 0, Nv * coordDim));
20869db5b827SMatthew G. Knepley           }
2087f45c9589SStefano Zampini         }
2088f45c9589SStefano Zampini       }
20896858538eSMatthew G. Knepley       PetscCall(PetscSectionSetUp(csCell));
20906858538eSMatthew G. Knepley       PetscCall(DMSetCellCoordinateSection(*dm, PETSC_DETERMINE, csCell));
2091f45c9589SStefano Zampini     }
2092066ea43fSLisandro Dalcin 
20939566063dSJacob Faibussowitsch     PetscCall(DMCreateLocalVector(cdm, &coordinates));
20949566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &pointCoords));
20956858538eSMatthew G. Knepley     PetscCall(PetscMalloc1(numVerts, &nodeMap));
20966858538eSMatthew G. Knepley     for (n = 0; n < numNodes; n++)
20976858538eSMatthew G. Knepley       if (mesh->vertexMap[n] >= 0) nodeMap[mesh->vertexMap[n]] = n;
20986858538eSMatthew G. Knepley     for (v = 0; v < numVerts; ++v) {
20996858538eSMatthew G. Knepley       PetscInt off, node = nodeMap[v];
21006858538eSMatthew G. Knepley 
21016858538eSMatthew G. Knepley       PetscCall(PetscSectionGetOffset(cs, numCells + v, &off));
21026858538eSMatthew G. Knepley       for (d = 0; d < coordDim; ++d) pointCoords[off + d] = (PetscReal)coords[node * 3 + d];
21036858538eSMatthew G. Knepley     }
21046858538eSMatthew G. Knepley     PetscCall(VecRestoreArray(coordinates, &pointCoords));
21056858538eSMatthew G. Knepley 
21060598e1a2SLisandro Dalcin     if (periodic) {
21079db5b827SMatthew G. Knepley       PetscInt cStart, cEnd;
21089db5b827SMatthew G. Knepley 
21099db5b827SMatthew G. Knepley       PetscCall(DMPlexGetHeightStratum(cdmCell, 0, &cStart, &cEnd));
21106858538eSMatthew G. Knepley       PetscCall(DMCreateLocalVector(cdmCell, &coordinatesCell));
21116858538eSMatthew G. Knepley       PetscCall(VecGetArray(coordinatesCell, &pointCoords));
21129db5b827SMatthew G. Knepley       for (PetscInt c = cStart; c < cEnd; ++c) {
21139db5b827SMatthew G. Knepley         GmshElement *elem    = mesh->elements + c - cStart;
21149db5b827SMatthew G. Knepley         PetscInt    *closure = NULL;
21159db5b827SMatthew G. Knepley         PetscInt     verts[8];
21169db5b827SMatthew G. Knepley         PetscInt     Ncl, Nv = 0;
21179db5b827SMatthew G. Knepley 
21189db5b827SMatthew G. Knepley         for (PetscInt v = 0; v < elem->numVerts; ++v) cone[v] = elem->nodes[v];
21199db5b827SMatthew G. Knepley         PetscCall(DMPlexReorderCell(cdmCell, c, cone));
21209db5b827SMatthew G. Knepley         PetscCall(DMPlexGetTransitiveClosure(cdmCell, c, PETSC_TRUE, &Ncl, &closure));
21219db5b827SMatthew G. Knepley         for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) {
21229db5b827SMatthew G. Knepley           if (closure[cl] >= vStart && closure[cl] < vEnd) verts[Nv++] = closure[cl];
2123331830f3SMatthew G. Knepley         }
21249db5b827SMatthew G. Knepley         PetscCheck(Nv == elem->numVerts, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of vertices %" PetscInt_FMT " in closure does not match number of vertices %" PetscInt_FMT " in Gmsh cell", Nv, elem->numVerts);
21259db5b827SMatthew G. Knepley         for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) {
21269db5b827SMatthew G. Knepley           const PetscInt point = closure[cl];
21279db5b827SMatthew G. Knepley           PetscInt       hStart, h;
21289db5b827SMatthew G. Knepley 
21299db5b827SMatthew G. Knepley           PetscCall(DMPlexGetPointHeight(cdmCell, point, &h));
21309db5b827SMatthew G. Knepley           if (h > maxHeight) continue;
21319db5b827SMatthew G. Knepley           PetscCall(DMPlexGetHeightStratum(cdmCell, h, &hStart, NULL));
21329db5b827SMatthew G. Knepley           if (PetscUnlikely(PetscBTLookup(periodicCells[h], point - hStart))) {
21339db5b827SMatthew G. Knepley             PetscInt *pclosure = NULL;
21349db5b827SMatthew G. Knepley             PetscInt  Npcl, off, v;
21359db5b827SMatthew G. Knepley 
21369db5b827SMatthew G. Knepley             PetscCall(PetscSectionGetOffset(csCell, point, &off));
21379db5b827SMatthew G. Knepley             PetscCall(DMPlexGetTransitiveClosure(cdmCell, point, PETSC_TRUE, &Npcl, &pclosure));
21389db5b827SMatthew G. Knepley             for (PetscInt pcl = 0; pcl < Npcl * 2; pcl += 2) {
21399db5b827SMatthew G. Knepley               if (pclosure[pcl] >= vStart && pclosure[pcl] < vEnd) {
21409db5b827SMatthew G. Knepley                 for (v = 0; v < Nv; ++v)
21419db5b827SMatthew G. Knepley                   if (verts[v] == pclosure[pcl]) break;
21429db5b827SMatthew G. Knepley                 PetscCheck(v < Nv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not find vertex %" PetscInt_FMT " in closure of cell %" PetscInt_FMT, pclosure[pcl], c);
21439db5b827SMatthew G. Knepley                 for (PetscInt d = 0; d < coordDim; ++d) pointCoords[off++] = (PetscReal)coords[cone[v] * 3 + d];
21449db5b827SMatthew G. Knepley                 ++v;
21459db5b827SMatthew G. Knepley               }
21469db5b827SMatthew G. Knepley             }
21479db5b827SMatthew G. Knepley             PetscCall(DMPlexRestoreTransitiveClosure(cdmCell, point, PETSC_TRUE, &Npcl, &pclosure));
21489db5b827SMatthew G. Knepley           }
21499db5b827SMatthew G. Knepley         }
21509db5b827SMatthew G. Knepley         PetscCall(DMPlexRestoreTransitiveClosure(cdmCell, c, PETSC_TRUE, &Ncl, &closure));
2151331830f3SMatthew G. Knepley       }
21526858538eSMatthew G. Knepley       PetscCall(VecSetBlockSize(coordinatesCell, coordDim));
21536858538eSMatthew G. Knepley       PetscCall(VecRestoreArray(coordinatesCell, &pointCoords));
21546858538eSMatthew G. Knepley       PetscCall(DMSetCellCoordinatesLocal(*dm, coordinatesCell));
21556858538eSMatthew G. Knepley       PetscCall(VecDestroy(&coordinatesCell));
2156331830f3SMatthew G. Knepley     }
21579db5b827SMatthew G. Knepley     PetscCall(PetscFree(nodeMap));
21586858538eSMatthew G. Knepley     PetscCall(PetscSectionDestroy(&csCell));
21596858538eSMatthew G. Knepley     PetscCall(DMDestroy(&cdmCell));
2160066ea43fSLisandro Dalcin   }
2161066ea43fSLisandro Dalcin 
21629566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
21639566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, coordDim));
21649566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(*dm, coordinates));
21659566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
216611c56cb0SLisandro Dalcin 
21679566063dSJacob Faibussowitsch   PetscCall(GmshMeshDestroy(&mesh));
21689566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&periodicVerts));
2169eae3dc7dSJacob Faibussowitsch   if (periodic) {
2170eae3dc7dSJacob Faibussowitsch     for (PetscInt h = 0; h <= maxHeight; ++h) PetscCall(PetscBTDestroy(periodicCells + h));
2171eae3dc7dSJacob Faibussowitsch     PetscCall(PetscFree(periodicCells));
2172eae3dc7dSJacob Faibussowitsch   }
217311c56cb0SLisandro Dalcin 
2174066ea43fSLisandro Dalcin   if (highOrder && project) {
2175066ea43fSLisandro Dalcin     PetscFE         fe;
2176066ea43fSLisandro Dalcin     const char      prefix[]   = "dm_plex_gmsh_project_";
2177066ea43fSLisandro Dalcin     PetscBool       continuity = periodic ? PETSC_FALSE : PETSC_TRUE;
2178066ea43fSLisandro Dalcin     PetscDTNodeType nodeType   = PETSCDTNODES_GAUSSJACOBI;
2179066ea43fSLisandro Dalcin 
2180066ea43fSLisandro Dalcin     if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */
21819566063dSJacob Faibussowitsch     PetscCall(GmshCreateFE(comm, prefix, isSimplex, continuity, nodeType, dim, coordDim, order, &fe));
21829566063dSJacob Faibussowitsch     PetscCall(PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_project_fe_view"));
21834c712d99Sksagiyam     PetscCall(DMSetCoordinateDisc(*dm, fe, PETSC_FALSE, PETSC_TRUE));
21849566063dSJacob Faibussowitsch     PetscCall(PetscFEDestroy(&fe));
2185066ea43fSLisandro Dalcin   }
2186066ea43fSLisandro Dalcin 
21879566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CreateGmsh, *dm, NULL, NULL, NULL));
21883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2189331830f3SMatthew G. Knepley }
2190