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