1331830f3SMatthew G. Knepley #define PETSCDM_DLL 2af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 3730356f6SLisandro Dalcin #include <petsc/private/hashmapi.h> 4331830f3SMatthew G. Knepley 5066ea43fSLisandro Dalcin #include <../src/dm/impls/plex/gmshlex.h> 6066ea43fSLisandro Dalcin 7066ea43fSLisandro Dalcin #define GMSH_LEXORDER_ITEM(T, p) \ 8066ea43fSLisandro Dalcin static int *GmshLexOrder_##T##_##p(void) \ 9066ea43fSLisandro Dalcin { \ 10066ea43fSLisandro Dalcin static int Gmsh_LexOrder_##T##_##p[GmshNumNodes_##T(p)] = {-1}; \ 11066ea43fSLisandro Dalcin int *lex = Gmsh_LexOrder_##T##_##p; \ 12066ea43fSLisandro Dalcin if (lex[0] == -1) (void)GmshLexOrder_##T(p, lex, 0); \ 13066ea43fSLisandro Dalcin return lex; \ 14066ea43fSLisandro Dalcin } 15066ea43fSLisandro Dalcin 16b9bf55e5SMatthew G. Knepley static int *GmshLexOrder_QUA_2_Serendipity(void) 17b9bf55e5SMatthew G. Knepley { 18b9bf55e5SMatthew G. Knepley static int Gmsh_LexOrder_QUA_2_Serendipity[9] = {-1}; 19b9bf55e5SMatthew G. Knepley int *lex = Gmsh_LexOrder_QUA_2_Serendipity; 20b9bf55e5SMatthew G. Knepley if (lex[0] == -1) { 21b9bf55e5SMatthew G. Knepley /* Vertices */ 22b9bf55e5SMatthew G. Knepley lex[0] = 0; lex[2] = 1; lex[8] = 2; lex[6] = 3; 23b9bf55e5SMatthew G. Knepley /* Edges */ 24b9bf55e5SMatthew G. Knepley lex[1] = 4; lex[5] = 5; lex[7] = 6; lex[3] = 7; 25b9bf55e5SMatthew G. Knepley /* Cell */ 26b9bf55e5SMatthew G. Knepley lex[4] = -8; 27b9bf55e5SMatthew G. Knepley } 28b9bf55e5SMatthew G. Knepley return lex; 29b9bf55e5SMatthew G. Knepley } 30b9bf55e5SMatthew G. Knepley 31b9bf55e5SMatthew G. Knepley static int *GmshLexOrder_HEX_2_Serendipity(void) 32b9bf55e5SMatthew G. Knepley { 33b9bf55e5SMatthew G. Knepley static int Gmsh_LexOrder_HEX_2_Serendipity[27] = {-1}; 34b9bf55e5SMatthew G. Knepley int *lex = Gmsh_LexOrder_HEX_2_Serendipity; 35b9bf55e5SMatthew G. Knepley if (lex[0] == -1) { 36b9bf55e5SMatthew G. Knepley /* Vertices */ 37b9bf55e5SMatthew G. Knepley lex[ 0] = 0; lex[ 2] = 1; lex[ 8] = 2; lex[ 6] = 3; 38b9bf55e5SMatthew G. Knepley lex[18] = 4; lex[20] = 5; lex[26] = 6; lex[24] = 7; 39b9bf55e5SMatthew G. Knepley /* Edges */ 40b9bf55e5SMatthew G. Knepley lex[ 1] = 8; lex[ 3] = 9; lex[ 9] = 10; lex[ 5] = 11; 41b9bf55e5SMatthew G. Knepley lex[11] = 12; lex[ 7] = 13; lex[17] = 14; lex[15] = 15; 42b9bf55e5SMatthew G. Knepley lex[19] = 16; lex[21] = 17; lex[23] = 18; lex[25] = 19; 43b9bf55e5SMatthew G. Knepley /* Faces */ 44b9bf55e5SMatthew G. Knepley lex[ 4] = -20; lex[10] = -21; lex[12] = -22; lex[14] = -23; 45b9bf55e5SMatthew G. Knepley lex[16] = -24; lex[22] = -25; 46b9bf55e5SMatthew G. Knepley /* Cell */ 47b9bf55e5SMatthew G. Knepley lex[13] = -26; 48b9bf55e5SMatthew G. Knepley } 49b9bf55e5SMatthew G. Knepley return lex; 50b9bf55e5SMatthew G. Knepley } 51b9bf55e5SMatthew G. Knepley 52066ea43fSLisandro Dalcin #define GMSH_LEXORDER_LIST(T) \ 53066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 1) \ 54066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 2) \ 55066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 3) \ 56066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 4) \ 57066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 5) \ 58066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 6) \ 59066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 7) \ 60066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 8) \ 61066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 9) \ 62066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 10) 63066ea43fSLisandro Dalcin 64066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(VTX, 0) 65066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(SEG) 66066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(TRI) 67066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(QUA) 68066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(TET) 69066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(HEX) 70066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(PRI) 71066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(PYR) 72066ea43fSLisandro Dalcin 73066ea43fSLisandro Dalcin typedef enum { 74066ea43fSLisandro Dalcin GMSH_VTX = 0, 75066ea43fSLisandro Dalcin GMSH_SEG = 1, 76066ea43fSLisandro Dalcin GMSH_TRI = 2, 77066ea43fSLisandro Dalcin GMSH_QUA = 3, 78066ea43fSLisandro Dalcin GMSH_TET = 4, 79066ea43fSLisandro Dalcin GMSH_HEX = 5, 80066ea43fSLisandro Dalcin GMSH_PRI = 6, 81066ea43fSLisandro Dalcin GMSH_PYR = 7, 82066ea43fSLisandro Dalcin GMSH_NUM_POLYTOPES = 8 83066ea43fSLisandro Dalcin } GmshPolytopeType; 84066ea43fSLisandro Dalcin 85de78e4feSLisandro Dalcin typedef struct { 860598e1a2SLisandro Dalcin int cellType; 87066ea43fSLisandro Dalcin int polytope; 880598e1a2SLisandro Dalcin int dim; 890598e1a2SLisandro Dalcin int order; 90066ea43fSLisandro Dalcin int numVerts; 910598e1a2SLisandro Dalcin int numNodes; 92066ea43fSLisandro Dalcin int* (*lexorder)(void); 930598e1a2SLisandro Dalcin } GmshCellInfo; 940598e1a2SLisandro Dalcin 95066ea43fSLisandro Dalcin #define GmshCellEntry(cellType, polytope, dim, order) \ 96066ea43fSLisandro Dalcin {cellType, GMSH_##polytope, dim, order, \ 97066ea43fSLisandro Dalcin GmshNumNodes_##polytope(1), \ 98066ea43fSLisandro Dalcin GmshNumNodes_##polytope(order), \ 99066ea43fSLisandro Dalcin GmshLexOrder_##polytope##_##order} 1000598e1a2SLisandro Dalcin 1010598e1a2SLisandro Dalcin static const GmshCellInfo GmshCellTable[] = { 102066ea43fSLisandro Dalcin GmshCellEntry( 15, VTX, 0, 0), 1030598e1a2SLisandro Dalcin 104066ea43fSLisandro Dalcin GmshCellEntry( 1, SEG, 1, 1), 105066ea43fSLisandro Dalcin GmshCellEntry( 8, SEG, 1, 2), 106066ea43fSLisandro Dalcin GmshCellEntry( 26, SEG, 1, 3), 107066ea43fSLisandro Dalcin GmshCellEntry( 27, SEG, 1, 4), 108066ea43fSLisandro Dalcin GmshCellEntry( 28, SEG, 1, 5), 109066ea43fSLisandro Dalcin GmshCellEntry( 62, SEG, 1, 6), 110066ea43fSLisandro Dalcin GmshCellEntry( 63, SEG, 1, 7), 111066ea43fSLisandro Dalcin GmshCellEntry( 64, SEG, 1, 8), 112066ea43fSLisandro Dalcin GmshCellEntry( 65, SEG, 1, 9), 113066ea43fSLisandro Dalcin GmshCellEntry( 66, SEG, 1, 10), 1140598e1a2SLisandro Dalcin 115066ea43fSLisandro Dalcin GmshCellEntry( 2, TRI, 2, 1), 116066ea43fSLisandro Dalcin GmshCellEntry( 9, TRI, 2, 2), 117066ea43fSLisandro Dalcin GmshCellEntry( 21, TRI, 2, 3), 118066ea43fSLisandro Dalcin GmshCellEntry( 23, TRI, 2, 4), 119066ea43fSLisandro Dalcin GmshCellEntry( 25, TRI, 2, 5), 120066ea43fSLisandro Dalcin GmshCellEntry( 42, TRI, 2, 6), 121066ea43fSLisandro Dalcin GmshCellEntry( 43, TRI, 2, 7), 122066ea43fSLisandro Dalcin GmshCellEntry( 44, TRI, 2, 8), 123066ea43fSLisandro Dalcin GmshCellEntry( 45, TRI, 2, 9), 124066ea43fSLisandro Dalcin GmshCellEntry( 46, TRI, 2, 10), 1250598e1a2SLisandro Dalcin 126066ea43fSLisandro Dalcin GmshCellEntry( 3, QUA, 2, 1), 127066ea43fSLisandro Dalcin GmshCellEntry( 10, QUA, 2, 2), 128b9bf55e5SMatthew G. Knepley {16, GMSH_QUA, 2, 2, 4, 8, GmshLexOrder_QUA_2_Serendipity}, 129066ea43fSLisandro Dalcin GmshCellEntry( 36, QUA, 2, 3), 130066ea43fSLisandro Dalcin GmshCellEntry( 37, QUA, 2, 4), 131066ea43fSLisandro Dalcin GmshCellEntry( 38, QUA, 2, 5), 132066ea43fSLisandro Dalcin GmshCellEntry( 47, QUA, 2, 6), 133066ea43fSLisandro Dalcin GmshCellEntry( 48, QUA, 2, 7), 134066ea43fSLisandro Dalcin GmshCellEntry( 49, QUA, 2, 8), 135066ea43fSLisandro Dalcin GmshCellEntry( 50, QUA, 2, 9), 136066ea43fSLisandro Dalcin GmshCellEntry( 51, QUA, 2, 10), 1370598e1a2SLisandro Dalcin 138066ea43fSLisandro Dalcin GmshCellEntry( 4, TET, 3, 1), 139066ea43fSLisandro Dalcin GmshCellEntry( 11, TET, 3, 2), 140066ea43fSLisandro Dalcin GmshCellEntry( 29, TET, 3, 3), 141066ea43fSLisandro Dalcin GmshCellEntry( 30, TET, 3, 4), 142066ea43fSLisandro Dalcin GmshCellEntry( 31, TET, 3, 5), 143066ea43fSLisandro Dalcin GmshCellEntry( 71, TET, 3, 6), 144066ea43fSLisandro Dalcin GmshCellEntry( 72, TET, 3, 7), 145066ea43fSLisandro Dalcin GmshCellEntry( 73, TET, 3, 8), 146066ea43fSLisandro Dalcin GmshCellEntry( 74, TET, 3, 9), 147066ea43fSLisandro Dalcin GmshCellEntry( 75, TET, 3, 10), 1480598e1a2SLisandro Dalcin 149066ea43fSLisandro Dalcin GmshCellEntry( 5, HEX, 3, 1), 150066ea43fSLisandro Dalcin GmshCellEntry( 12, HEX, 3, 2), 151b9bf55e5SMatthew G. Knepley {17, GMSH_HEX, 3, 2, 8, 20, GmshLexOrder_HEX_2_Serendipity}, 152066ea43fSLisandro Dalcin GmshCellEntry( 92, HEX, 3, 3), 153066ea43fSLisandro Dalcin GmshCellEntry( 93, HEX, 3, 4), 154066ea43fSLisandro Dalcin GmshCellEntry( 94, HEX, 3, 5), 155066ea43fSLisandro Dalcin GmshCellEntry( 95, HEX, 3, 6), 156066ea43fSLisandro Dalcin GmshCellEntry( 96, HEX, 3, 7), 157066ea43fSLisandro Dalcin GmshCellEntry( 97, HEX, 3, 8), 158066ea43fSLisandro Dalcin GmshCellEntry( 98, HEX, 3, 9), 159066ea43fSLisandro Dalcin GmshCellEntry( -1, HEX, 3, 10), 1600598e1a2SLisandro Dalcin 161066ea43fSLisandro Dalcin GmshCellEntry( 6, PRI, 3, 1), 162066ea43fSLisandro Dalcin GmshCellEntry( 13, PRI, 3, 2), 163066ea43fSLisandro Dalcin GmshCellEntry( 90, PRI, 3, 3), 164066ea43fSLisandro Dalcin GmshCellEntry( 91, PRI, 3, 4), 165066ea43fSLisandro Dalcin GmshCellEntry(106, PRI, 3, 5), 166066ea43fSLisandro Dalcin GmshCellEntry(107, PRI, 3, 6), 167066ea43fSLisandro Dalcin GmshCellEntry(108, PRI, 3, 7), 168066ea43fSLisandro Dalcin GmshCellEntry(109, PRI, 3, 8), 169066ea43fSLisandro Dalcin GmshCellEntry(110, PRI, 3, 9), 170066ea43fSLisandro Dalcin GmshCellEntry( -1, PRI, 3, 10), 1710598e1a2SLisandro Dalcin 172066ea43fSLisandro Dalcin GmshCellEntry( 7, PYR, 3, 1), 173066ea43fSLisandro Dalcin GmshCellEntry( 14, PYR, 3, 2), 174066ea43fSLisandro Dalcin GmshCellEntry(118, PYR, 3, 3), 175066ea43fSLisandro Dalcin GmshCellEntry(119, PYR, 3, 4), 176066ea43fSLisandro Dalcin GmshCellEntry(120, PYR, 3, 5), 177066ea43fSLisandro Dalcin GmshCellEntry(121, PYR, 3, 6), 178066ea43fSLisandro Dalcin GmshCellEntry(122, PYR, 3, 7), 179066ea43fSLisandro Dalcin GmshCellEntry(123, PYR, 3, 8), 180066ea43fSLisandro Dalcin GmshCellEntry(124, PYR, 3, 9), 181066ea43fSLisandro Dalcin GmshCellEntry( -1, PYR, 3, 10) 1820598e1a2SLisandro Dalcin 1830598e1a2SLisandro Dalcin #if 0 184066ea43fSLisandro Dalcin {20, GMSH_TRI, 2, 3, 3, 9, NULL}, 185066ea43fSLisandro Dalcin {18, GMSH_PRI, 3, 2, 6, 15, NULL}, 186066ea43fSLisandro Dalcin {19, GMSH_PYR, 3, 2, 5, 13, NULL}, 1870598e1a2SLisandro Dalcin #endif 1880598e1a2SLisandro Dalcin }; 1890598e1a2SLisandro Dalcin 1900598e1a2SLisandro Dalcin static GmshCellInfo GmshCellMap[150]; 1910598e1a2SLisandro Dalcin 1920598e1a2SLisandro Dalcin static PetscErrorCode GmshCellInfoSetUp(void) 1930598e1a2SLisandro Dalcin { 1940598e1a2SLisandro Dalcin size_t i, n; 1950598e1a2SLisandro Dalcin static PetscBool called = PETSC_FALSE; 1960598e1a2SLisandro Dalcin 1970598e1a2SLisandro Dalcin if (called) return 0; 1980598e1a2SLisandro Dalcin PetscFunctionBegin; 1990598e1a2SLisandro Dalcin called = PETSC_TRUE; 2000598e1a2SLisandro Dalcin n = sizeof(GmshCellMap)/sizeof(GmshCellMap[0]); 2010598e1a2SLisandro Dalcin for (i = 0; i < n; ++i) { 2020598e1a2SLisandro Dalcin GmshCellMap[i].cellType = -1; 203066ea43fSLisandro Dalcin GmshCellMap[i].polytope = -1; 2040598e1a2SLisandro Dalcin } 2050598e1a2SLisandro Dalcin n = sizeof(GmshCellTable)/sizeof(GmshCellTable[0]); 206066ea43fSLisandro Dalcin for (i = 0; i < n; ++i) { 207066ea43fSLisandro Dalcin if (GmshCellTable[i].cellType <= 0) continue; 208066ea43fSLisandro Dalcin GmshCellMap[GmshCellTable[i].cellType] = GmshCellTable[i]; 209066ea43fSLisandro Dalcin } 2100598e1a2SLisandro Dalcin PetscFunctionReturn(0); 2110598e1a2SLisandro Dalcin } 2120598e1a2SLisandro Dalcin 2130598e1a2SLisandro Dalcin #define GmshCellTypeCheck(ct) 0; do { \ 2140598e1a2SLisandro Dalcin const int _ct_ = (int)ct; \ 2150598e1a2SLisandro Dalcin if (_ct_ < 0 || _ct_ >= (int)(sizeof(GmshCellMap)/sizeof(GmshCellMap[0]))) \ 21698921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid Gmsh element type %d", _ct_); \ 2170598e1a2SLisandro Dalcin if (GmshCellMap[_ct_].cellType != _ct_) \ 21898921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported Gmsh element type %d", _ct_); \ 219066ea43fSLisandro Dalcin if (GmshCellMap[_ct_].polytope == -1) \ 22098921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported Gmsh element type %d", _ct_); \ 2210598e1a2SLisandro Dalcin } while (0) 2220598e1a2SLisandro Dalcin 2230598e1a2SLisandro Dalcin typedef struct { 224698a79b9SLisandro Dalcin PetscViewer viewer; 225698a79b9SLisandro Dalcin int fileFormat; 226698a79b9SLisandro Dalcin int dataSize; 227698a79b9SLisandro Dalcin PetscBool binary; 228698a79b9SLisandro Dalcin PetscBool byteSwap; 229698a79b9SLisandro Dalcin size_t wlen; 230698a79b9SLisandro Dalcin void *wbuf; 231698a79b9SLisandro Dalcin size_t slen; 232698a79b9SLisandro Dalcin void *sbuf; 2330598e1a2SLisandro Dalcin PetscInt *nbuf; 2340598e1a2SLisandro Dalcin PetscInt nodeStart; 2350598e1a2SLisandro Dalcin PetscInt nodeEnd; 23633a088b6SMatthew G. Knepley PetscInt *nodeMap; 237698a79b9SLisandro Dalcin } GmshFile; 238de78e4feSLisandro Dalcin 239698a79b9SLisandro Dalcin static PetscErrorCode GmshBufferGet(GmshFile *gmsh, size_t count, size_t eltsize, void *buf) 240de78e4feSLisandro Dalcin { 241de78e4feSLisandro Dalcin size_t size = count * eltsize; 24211c56cb0SLisandro Dalcin 24311c56cb0SLisandro Dalcin PetscFunctionBegin; 244698a79b9SLisandro Dalcin if (gmsh->wlen < size) { 245*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(gmsh->wbuf)); 246*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc(size, &gmsh->wbuf)); 247698a79b9SLisandro Dalcin gmsh->wlen = size; 248de78e4feSLisandro Dalcin } 249698a79b9SLisandro Dalcin *(void**)buf = size ? gmsh->wbuf : NULL; 250de78e4feSLisandro Dalcin PetscFunctionReturn(0); 251de78e4feSLisandro Dalcin } 252de78e4feSLisandro Dalcin 253698a79b9SLisandro Dalcin static PetscErrorCode GmshBufferSizeGet(GmshFile *gmsh, size_t count, void *buf) 254698a79b9SLisandro Dalcin { 255698a79b9SLisandro Dalcin size_t dataSize = (size_t)gmsh->dataSize; 256698a79b9SLisandro Dalcin size_t size = count * dataSize; 257698a79b9SLisandro Dalcin 258698a79b9SLisandro Dalcin PetscFunctionBegin; 259698a79b9SLisandro Dalcin if (gmsh->slen < size) { 260*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(gmsh->sbuf)); 261*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc(size, &gmsh->sbuf)); 262698a79b9SLisandro Dalcin gmsh->slen = size; 263698a79b9SLisandro Dalcin } 264698a79b9SLisandro Dalcin *(void**)buf = size ? gmsh->sbuf : NULL; 265698a79b9SLisandro Dalcin PetscFunctionReturn(0); 266698a79b9SLisandro Dalcin } 267698a79b9SLisandro Dalcin 268698a79b9SLisandro Dalcin static PetscErrorCode GmshRead(GmshFile *gmsh, void *buf, PetscInt count, PetscDataType dtype) 269de78e4feSLisandro Dalcin { 270de78e4feSLisandro Dalcin PetscFunctionBegin; 271*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(gmsh->viewer, buf, count, NULL, dtype)); 272*5f80ce2aSJacob Faibussowitsch if (gmsh->byteSwap) CHKERRQ(PetscByteSwap(buf, dtype, count)); 273698a79b9SLisandro Dalcin PetscFunctionReturn(0); 274698a79b9SLisandro Dalcin } 275698a79b9SLisandro Dalcin 276698a79b9SLisandro Dalcin static PetscErrorCode GmshReadString(GmshFile *gmsh, char *buf, PetscInt count) 277698a79b9SLisandro Dalcin { 278698a79b9SLisandro Dalcin PetscFunctionBegin; 279*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(gmsh->viewer, buf, count, NULL, PETSC_STRING)); 280698a79b9SLisandro Dalcin PetscFunctionReturn(0); 281698a79b9SLisandro Dalcin } 282698a79b9SLisandro Dalcin 283d6689ca9SLisandro Dalcin static PetscErrorCode GmshMatch(PETSC_UNUSED GmshFile *gmsh, const char Section[], char line[PETSC_MAX_PATH_LEN], PetscBool *match) 284d6689ca9SLisandro Dalcin { 285d6689ca9SLisandro Dalcin PetscFunctionBegin; 286*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcmp(line, Section, match)); 287d6689ca9SLisandro Dalcin PetscFunctionReturn(0); 288d6689ca9SLisandro Dalcin } 289d6689ca9SLisandro Dalcin 290d6689ca9SLisandro Dalcin static PetscErrorCode GmshExpect(GmshFile *gmsh, const char Section[], char line[PETSC_MAX_PATH_LEN]) 291d6689ca9SLisandro Dalcin { 292d6689ca9SLisandro Dalcin PetscBool match; 293d6689ca9SLisandro Dalcin 294d6689ca9SLisandro Dalcin PetscFunctionBegin; 295*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshMatch(gmsh, Section, line, &match)); 2962c71b3e2SJacob Faibussowitsch PetscCheckFalse(!match,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file, expecting %s",Section); 297d6689ca9SLisandro Dalcin PetscFunctionReturn(0); 298d6689ca9SLisandro Dalcin } 299d6689ca9SLisandro Dalcin 300d6689ca9SLisandro Dalcin static PetscErrorCode GmshReadSection(GmshFile *gmsh, char line[PETSC_MAX_PATH_LEN]) 301d6689ca9SLisandro Dalcin { 302d6689ca9SLisandro Dalcin PetscBool match; 303d6689ca9SLisandro Dalcin 304d6689ca9SLisandro Dalcin PetscFunctionBegin; 305d6689ca9SLisandro Dalcin while (PETSC_TRUE) { 306*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadString(gmsh, line, 1)); 307*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshMatch(gmsh, "$Comments", line, &match)); 308d6689ca9SLisandro Dalcin if (!match) break; 309d6689ca9SLisandro Dalcin while (PETSC_TRUE) { 310*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadString(gmsh, line, 1)); 311*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshMatch(gmsh, "$EndComments", line, &match)); 312d6689ca9SLisandro Dalcin if (match) break; 313d6689ca9SLisandro Dalcin } 314d6689ca9SLisandro Dalcin } 315d6689ca9SLisandro Dalcin PetscFunctionReturn(0); 316d6689ca9SLisandro Dalcin } 317d6689ca9SLisandro Dalcin 318d6689ca9SLisandro Dalcin static PetscErrorCode GmshReadEndSection(GmshFile *gmsh, const char EndSection[], char line[PETSC_MAX_PATH_LEN]) 319d6689ca9SLisandro Dalcin { 320d6689ca9SLisandro Dalcin PetscFunctionBegin; 321*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadString(gmsh, line, 1)); 322*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshExpect(gmsh, EndSection, line)); 323d6689ca9SLisandro Dalcin PetscFunctionReturn(0); 324d6689ca9SLisandro Dalcin } 325d6689ca9SLisandro Dalcin 326698a79b9SLisandro Dalcin static PetscErrorCode GmshReadSize(GmshFile *gmsh, PetscInt *buf, PetscInt count) 327698a79b9SLisandro Dalcin { 328698a79b9SLisandro Dalcin PetscInt i; 329698a79b9SLisandro Dalcin size_t dataSize = (size_t)gmsh->dataSize; 330698a79b9SLisandro Dalcin 331698a79b9SLisandro Dalcin PetscFunctionBegin; 332698a79b9SLisandro Dalcin if (dataSize == sizeof(PetscInt)) { 333*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshRead(gmsh, buf, count, PETSC_INT)); 334698a79b9SLisandro Dalcin } else if (dataSize == sizeof(int)) { 335698a79b9SLisandro Dalcin int *ibuf = NULL; 336*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshBufferSizeGet(gmsh, count, &ibuf)); 337*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshRead(gmsh, ibuf, count, PETSC_ENUM)); 338698a79b9SLisandro Dalcin for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i]; 339698a79b9SLisandro Dalcin } else if (dataSize == sizeof(long)) { 340698a79b9SLisandro Dalcin long *ibuf = NULL; 341*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshBufferSizeGet(gmsh, count, &ibuf)); 342*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshRead(gmsh, ibuf, count, PETSC_LONG)); 343698a79b9SLisandro Dalcin for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i]; 344698a79b9SLisandro Dalcin } else if (dataSize == sizeof(PetscInt64)) { 345698a79b9SLisandro Dalcin PetscInt64 *ibuf = NULL; 346*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshBufferSizeGet(gmsh, count, &ibuf)); 347*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshRead(gmsh, ibuf, count, PETSC_INT64)); 348698a79b9SLisandro Dalcin for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i]; 349698a79b9SLisandro Dalcin } 350698a79b9SLisandro Dalcin PetscFunctionReturn(0); 351698a79b9SLisandro Dalcin } 352698a79b9SLisandro Dalcin 353698a79b9SLisandro Dalcin static PetscErrorCode GmshReadInt(GmshFile *gmsh, int *buf, PetscInt count) 354698a79b9SLisandro Dalcin { 355698a79b9SLisandro Dalcin PetscFunctionBegin; 356*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshRead(gmsh, buf, count, PETSC_ENUM)); 357698a79b9SLisandro Dalcin PetscFunctionReturn(0); 358698a79b9SLisandro Dalcin } 359698a79b9SLisandro Dalcin 360698a79b9SLisandro Dalcin static PetscErrorCode GmshReadDouble(GmshFile *gmsh, double *buf, PetscInt count) 361698a79b9SLisandro Dalcin { 362698a79b9SLisandro Dalcin PetscFunctionBegin; 363*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshRead(gmsh, buf, count, PETSC_DOUBLE)); 364de78e4feSLisandro Dalcin PetscFunctionReturn(0); 365de78e4feSLisandro Dalcin } 366de78e4feSLisandro Dalcin 367de78e4feSLisandro Dalcin typedef struct { 3680598e1a2SLisandro Dalcin PetscInt id; /* Entity ID */ 3690598e1a2SLisandro Dalcin PetscInt dim; /* Dimension */ 370de78e4feSLisandro Dalcin double bbox[6]; /* Bounding box */ 371de78e4feSLisandro Dalcin PetscInt numTags; /* Size of tag array */ 372de78e4feSLisandro Dalcin int tags[4]; /* Tag array */ 373de78e4feSLisandro Dalcin } GmshEntity; 374de78e4feSLisandro Dalcin 375de78e4feSLisandro Dalcin typedef struct { 376730356f6SLisandro Dalcin GmshEntity *entity[4]; 377730356f6SLisandro Dalcin PetscHMapI entityMap[4]; 378730356f6SLisandro Dalcin } GmshEntities; 379730356f6SLisandro Dalcin 380698a79b9SLisandro Dalcin static PetscErrorCode GmshEntitiesCreate(PetscInt count[4], GmshEntities **entities) 381730356f6SLisandro Dalcin { 382730356f6SLisandro Dalcin PetscInt dim; 383730356f6SLisandro Dalcin 384730356f6SLisandro Dalcin PetscFunctionBegin; 385*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscNew(entities)); 386730356f6SLisandro Dalcin for (dim = 0; dim < 4; ++dim) { 387*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(count[dim], &(*entities)->entity[dim])); 388*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHMapICreate(&(*entities)->entityMap[dim])); 389730356f6SLisandro Dalcin } 390730356f6SLisandro Dalcin PetscFunctionReturn(0); 391730356f6SLisandro Dalcin } 392730356f6SLisandro Dalcin 3930598e1a2SLisandro Dalcin static PetscErrorCode GmshEntitiesDestroy(GmshEntities **entities) 3940598e1a2SLisandro Dalcin { 3950598e1a2SLisandro Dalcin PetscInt dim; 3960598e1a2SLisandro Dalcin 3970598e1a2SLisandro Dalcin PetscFunctionBegin; 3980598e1a2SLisandro Dalcin if (!*entities) PetscFunctionReturn(0); 3990598e1a2SLisandro Dalcin for (dim = 0; dim < 4; ++dim) { 400*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree((*entities)->entity[dim])); 401*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHMapIDestroy(&(*entities)->entityMap[dim])); 4020598e1a2SLisandro Dalcin } 403*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree((*entities))); 4040598e1a2SLisandro Dalcin PetscFunctionReturn(0); 4050598e1a2SLisandro Dalcin } 4060598e1a2SLisandro Dalcin 407730356f6SLisandro Dalcin static PetscErrorCode GmshEntitiesAdd(GmshEntities *entities, PetscInt index, PetscInt dim, PetscInt eid, GmshEntity** entity) 408730356f6SLisandro Dalcin { 409730356f6SLisandro Dalcin PetscFunctionBegin; 410*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHMapISet(entities->entityMap[dim], eid, index)); 411730356f6SLisandro Dalcin entities->entity[dim][index].dim = dim; 412730356f6SLisandro Dalcin entities->entity[dim][index].id = eid; 413730356f6SLisandro Dalcin if (entity) *entity = &entities->entity[dim][index]; 414730356f6SLisandro Dalcin PetscFunctionReturn(0); 415730356f6SLisandro Dalcin } 416730356f6SLisandro Dalcin 417730356f6SLisandro Dalcin static PetscErrorCode GmshEntitiesGet(GmshEntities *entities, PetscInt dim, PetscInt eid, GmshEntity** entity) 418730356f6SLisandro Dalcin { 419730356f6SLisandro Dalcin PetscInt index; 420730356f6SLisandro Dalcin 421730356f6SLisandro Dalcin PetscFunctionBegin; 422*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHMapIGet(entities->entityMap[dim], eid, &index)); 423730356f6SLisandro Dalcin *entity = &entities->entity[dim][index]; 424730356f6SLisandro Dalcin PetscFunctionReturn(0); 425730356f6SLisandro Dalcin } 426730356f6SLisandro Dalcin 4270598e1a2SLisandro Dalcin typedef struct { 4280598e1a2SLisandro Dalcin PetscInt *id; /* Node IDs */ 4290598e1a2SLisandro Dalcin double *xyz; /* Coordinates */ 43081a1af93SMatthew G. Knepley PetscInt *tag; /* Physical tag */ 4310598e1a2SLisandro Dalcin } GmshNodes; 4320598e1a2SLisandro Dalcin 4330598e1a2SLisandro Dalcin static PetscErrorCode GmshNodesCreate(PetscInt count, GmshNodes **nodes) 434730356f6SLisandro Dalcin { 435730356f6SLisandro Dalcin PetscFunctionBegin; 436*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscNew(nodes)); 437*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(count*1, &(*nodes)->id)); 438*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(count*3, &(*nodes)->xyz)); 439*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(count*1, &(*nodes)->tag)); 4400598e1a2SLisandro Dalcin PetscFunctionReturn(0); 441730356f6SLisandro Dalcin } 4420598e1a2SLisandro Dalcin 4430598e1a2SLisandro Dalcin static PetscErrorCode GmshNodesDestroy(GmshNodes **nodes) 4440598e1a2SLisandro Dalcin { 4450598e1a2SLisandro Dalcin PetscFunctionBegin; 4460598e1a2SLisandro Dalcin if (!*nodes) PetscFunctionReturn(0); 447*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree((*nodes)->id)); 448*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree((*nodes)->xyz)); 449*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree((*nodes)->tag)); 450*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree((*nodes))); 451730356f6SLisandro Dalcin PetscFunctionReturn(0); 452730356f6SLisandro Dalcin } 453730356f6SLisandro Dalcin 454730356f6SLisandro Dalcin typedef struct { 4550598e1a2SLisandro Dalcin PetscInt id; /* Element ID */ 4560598e1a2SLisandro Dalcin PetscInt dim; /* Dimension */ 457de78e4feSLisandro Dalcin PetscInt cellType; /* Cell type */ 4580598e1a2SLisandro Dalcin PetscInt numVerts; /* Size of vertex array */ 459de78e4feSLisandro Dalcin PetscInt numNodes; /* Size of node array */ 4600598e1a2SLisandro Dalcin PetscInt *nodes; /* Vertex/Node array */ 46181a1af93SMatthew G. Knepley PetscInt numTags; /* Size of physical tag array */ 46281a1af93SMatthew G. Knepley int tags[4]; /* Physical tag array */ 463de78e4feSLisandro Dalcin } GmshElement; 464de78e4feSLisandro Dalcin 4650598e1a2SLisandro Dalcin static PetscErrorCode GmshElementsCreate(PetscInt count, GmshElement **elements) 4660598e1a2SLisandro Dalcin { 4670598e1a2SLisandro Dalcin PetscFunctionBegin; 468*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(count, elements)); 4690598e1a2SLisandro Dalcin PetscFunctionReturn(0); 4700598e1a2SLisandro Dalcin } 4710598e1a2SLisandro Dalcin 4720598e1a2SLisandro Dalcin static PetscErrorCode GmshElementsDestroy(GmshElement **elements) 4730598e1a2SLisandro Dalcin { 4740598e1a2SLisandro Dalcin PetscFunctionBegin; 4750598e1a2SLisandro Dalcin if (!*elements) PetscFunctionReturn(0); 476*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(*elements)); 4770598e1a2SLisandro Dalcin PetscFunctionReturn(0); 4780598e1a2SLisandro Dalcin } 4790598e1a2SLisandro Dalcin 4800598e1a2SLisandro Dalcin typedef struct { 4810598e1a2SLisandro Dalcin PetscInt dim; 482066ea43fSLisandro Dalcin PetscInt order; 4830598e1a2SLisandro Dalcin GmshEntities *entities; 4840598e1a2SLisandro Dalcin PetscInt numNodes; 4850598e1a2SLisandro Dalcin GmshNodes *nodelist; 4860598e1a2SLisandro Dalcin PetscInt numElems; 4870598e1a2SLisandro Dalcin GmshElement *elements; 4880598e1a2SLisandro Dalcin PetscInt numVerts; 4890598e1a2SLisandro Dalcin PetscInt numCells; 4900598e1a2SLisandro Dalcin PetscInt *periodMap; 4910598e1a2SLisandro Dalcin PetscInt *vertexMap; 4920598e1a2SLisandro Dalcin PetscSegBuffer segbuf; 493a45dabc8SMatthew G. Knepley PetscInt numRegions; 494a45dabc8SMatthew G. Knepley PetscInt *regionTags; 495a45dabc8SMatthew G. Knepley char **regionNames; 4960598e1a2SLisandro Dalcin } GmshMesh; 4970598e1a2SLisandro Dalcin 4980598e1a2SLisandro Dalcin static PetscErrorCode GmshMeshCreate(GmshMesh **mesh) 4990598e1a2SLisandro Dalcin { 5000598e1a2SLisandro Dalcin PetscFunctionBegin; 501*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscNew(mesh)); 502*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSegBufferCreate(sizeof(PetscInt), 0, &(*mesh)->segbuf)); 5030598e1a2SLisandro Dalcin PetscFunctionReturn(0); 5040598e1a2SLisandro Dalcin } 5050598e1a2SLisandro Dalcin 5060598e1a2SLisandro Dalcin static PetscErrorCode GmshMeshDestroy(GmshMesh **mesh) 5070598e1a2SLisandro Dalcin { 508a45dabc8SMatthew G. Knepley PetscInt r; 5090598e1a2SLisandro Dalcin 5100598e1a2SLisandro Dalcin PetscFunctionBegin; 5110598e1a2SLisandro Dalcin if (!*mesh) PetscFunctionReturn(0); 512*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshEntitiesDestroy(&(*mesh)->entities)); 513*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshNodesDestroy(&(*mesh)->nodelist)); 514*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshElementsDestroy(&(*mesh)->elements)); 515*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree((*mesh)->periodMap)); 516*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree((*mesh)->vertexMap)); 517*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSegBufferDestroy(&(*mesh)->segbuf)); 518*5f80ce2aSJacob Faibussowitsch for (r = 0; r < (*mesh)->numRegions; ++r) CHKERRQ(PetscFree((*mesh)->regionNames[r])); 519*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2((*mesh)->regionTags, (*mesh)->regionNames)); 520*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree((*mesh))); 5210598e1a2SLisandro Dalcin PetscFunctionReturn(0); 5220598e1a2SLisandro Dalcin } 5230598e1a2SLisandro Dalcin 5240598e1a2SLisandro Dalcin static PetscErrorCode GmshReadNodes_v22(GmshFile *gmsh, GmshMesh *mesh) 525de78e4feSLisandro Dalcin { 526698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 527698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 528de78e4feSLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 5290598e1a2SLisandro Dalcin int n, num, nid, snum; 5300598e1a2SLisandro Dalcin GmshNodes *nodes; 531de78e4feSLisandro Dalcin 532de78e4feSLisandro Dalcin PetscFunctionBegin; 533*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 534698a79b9SLisandro Dalcin snum = sscanf(line, "%d", &num); 5352c71b3e2SJacob Faibussowitsch PetscCheckFalse(snum != 1,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 536*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshNodesCreate(num, &nodes)); 5370598e1a2SLisandro Dalcin mesh->numNodes = num; 5380598e1a2SLisandro Dalcin mesh->nodelist = nodes; 5390598e1a2SLisandro Dalcin for (n = 0; n < num; ++n) { 5400598e1a2SLisandro Dalcin double *xyz = nodes->xyz + n*3; 541*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM)); 542*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE)); 543*5f80ce2aSJacob Faibussowitsch if (byteSwap) CHKERRQ(PetscByteSwap(&nid, PETSC_ENUM, 1)); 544*5f80ce2aSJacob Faibussowitsch if (byteSwap) CHKERRQ(PetscByteSwap(xyz, PETSC_DOUBLE, 3)); 5450598e1a2SLisandro Dalcin nodes->id[n] = nid; 54681a1af93SMatthew G. Knepley nodes->tag[n] = -1; 54711c56cb0SLisandro Dalcin } 54811c56cb0SLisandro Dalcin PetscFunctionReturn(0); 54911c56cb0SLisandro Dalcin } 55011c56cb0SLisandro Dalcin 551de78e4feSLisandro Dalcin /* Gmsh elements can be of any dimension/co-dimension, so we need to traverse the 552de78e4feSLisandro Dalcin file contents multiple times to figure out the true number of cells and facets 553de78e4feSLisandro Dalcin in the given mesh. To make this more efficient we read the file contents only 554de78e4feSLisandro Dalcin once and store them in memory, while determining the true number of cells. */ 5550598e1a2SLisandro Dalcin static PetscErrorCode GmshReadElements_v22(GmshFile* gmsh, GmshMesh *mesh) 55611c56cb0SLisandro Dalcin { 557698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 558698a79b9SLisandro Dalcin PetscBool binary = gmsh->binary; 559698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 560de78e4feSLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 5610598e1a2SLisandro Dalcin int i, c, p, num, ibuf[1+4+1000], snum; 5620598e1a2SLisandro Dalcin int cellType, numElem, numVerts, numNodes, numTags; 563df032b82SMatthew G. Knepley GmshElement *elements; 5640598e1a2SLisandro Dalcin PetscInt *nodeMap = gmsh->nodeMap; 565df032b82SMatthew G. Knepley 566df032b82SMatthew G. Knepley PetscFunctionBegin; 567*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 568698a79b9SLisandro Dalcin snum = sscanf(line, "%d", &num); 5692c71b3e2SJacob Faibussowitsch PetscCheckFalse(snum != 1,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 570*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshElementsCreate(num, &elements)); 5710598e1a2SLisandro Dalcin mesh->numElems = num; 5720598e1a2SLisandro Dalcin mesh->elements = elements; 573698a79b9SLisandro Dalcin for (c = 0; c < num;) { 574*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM)); 575*5f80ce2aSJacob Faibussowitsch if (byteSwap) CHKERRQ(PetscByteSwap(ibuf, PETSC_ENUM, 3)); 5760598e1a2SLisandro Dalcin 5770598e1a2SLisandro Dalcin cellType = binary ? ibuf[0] : ibuf[1]; 5780598e1a2SLisandro Dalcin numElem = binary ? ibuf[1] : 1; 579df032b82SMatthew G. Knepley numTags = ibuf[2]; 5800598e1a2SLisandro Dalcin 581*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshCellTypeCheck(cellType)); 5820598e1a2SLisandro Dalcin numVerts = GmshCellMap[cellType].numVerts; 5830598e1a2SLisandro Dalcin numNodes = GmshCellMap[cellType].numNodes; 5840598e1a2SLisandro Dalcin 585df032b82SMatthew G. Knepley for (i = 0; i < numElem; ++i, ++c) { 5860598e1a2SLisandro Dalcin GmshElement *element = elements + c; 5870598e1a2SLisandro Dalcin const int off = binary ? 0 : 1, nint = 1 + numTags + numNodes - off; 5880598e1a2SLisandro Dalcin const int *id = ibuf, *nodes = ibuf + 1 + numTags, *tags = ibuf + 1; 589*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, ibuf+off, nint, NULL, PETSC_ENUM)); 590*5f80ce2aSJacob Faibussowitsch if (byteSwap) CHKERRQ(PetscByteSwap(ibuf+off, PETSC_ENUM, nint)); 5910598e1a2SLisandro Dalcin element->id = id[0]; 5920598e1a2SLisandro Dalcin element->dim = GmshCellMap[cellType].dim; 5930598e1a2SLisandro Dalcin element->cellType = cellType; 5940598e1a2SLisandro Dalcin element->numVerts = numVerts; 5950598e1a2SLisandro Dalcin element->numNodes = numNodes; 5960598e1a2SLisandro Dalcin element->numTags = PetscMin(numTags, 4); 597*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes)); 5980598e1a2SLisandro Dalcin for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]]; 5990598e1a2SLisandro Dalcin for (p = 0; p < element->numTags; p++) element->tags[p] = tags[p]; 600df032b82SMatthew G. Knepley } 601df032b82SMatthew G. Knepley } 602df032b82SMatthew G. Knepley PetscFunctionReturn(0); 603df032b82SMatthew G. Knepley } 6047d282ae0SMichael Lange 605de78e4feSLisandro Dalcin /* 606de78e4feSLisandro Dalcin $Entities 607de78e4feSLisandro Dalcin numPoints(unsigned long) numCurves(unsigned long) 608de78e4feSLisandro Dalcin numSurfaces(unsigned long) numVolumes(unsigned long) 609de78e4feSLisandro Dalcin // points 610de78e4feSLisandro Dalcin tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 611de78e4feSLisandro Dalcin boxMaxX(double) boxMaxY(double) boxMaxZ(double) 612de78e4feSLisandro Dalcin numPhysicals(unsigned long) phyisicalTag[...](int) 613de78e4feSLisandro Dalcin ... 614de78e4feSLisandro Dalcin // curves 615de78e4feSLisandro Dalcin tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 616de78e4feSLisandro Dalcin boxMaxX(double) boxMaxY(double) boxMaxZ(double) 617de78e4feSLisandro Dalcin numPhysicals(unsigned long) physicalTag[...](int) 618de78e4feSLisandro Dalcin numBREPVert(unsigned long) tagBREPVert[...](int) 619de78e4feSLisandro Dalcin ... 620de78e4feSLisandro Dalcin // surfaces 621de78e4feSLisandro Dalcin tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 622de78e4feSLisandro Dalcin boxMaxX(double) boxMaxY(double) boxMaxZ(double) 623de78e4feSLisandro Dalcin numPhysicals(unsigned long) physicalTag[...](int) 624de78e4feSLisandro Dalcin numBREPCurve(unsigned long) tagBREPCurve[...](int) 625de78e4feSLisandro Dalcin ... 626de78e4feSLisandro Dalcin // volumes 627de78e4feSLisandro Dalcin tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 628de78e4feSLisandro Dalcin boxMaxX(double) boxMaxY(double) boxMaxZ(double) 629de78e4feSLisandro Dalcin numPhysicals(unsigned long) physicalTag[...](int) 630de78e4feSLisandro Dalcin numBREPSurfaces(unsigned long) tagBREPSurfaces[...](int) 631de78e4feSLisandro Dalcin ... 632de78e4feSLisandro Dalcin $EndEntities 633de78e4feSLisandro Dalcin */ 6340598e1a2SLisandro Dalcin static PetscErrorCode GmshReadEntities_v40(GmshFile *gmsh, GmshMesh *mesh) 635de78e4feSLisandro Dalcin { 636698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 637698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 638698a79b9SLisandro Dalcin long index, num, lbuf[4]; 639730356f6SLisandro Dalcin int dim, eid, numTags, *ibuf, t; 640698a79b9SLisandro Dalcin PetscInt count[4], i; 641a5ba3d71SLisandro Dalcin GmshEntity *entity = NULL; 642de78e4feSLisandro Dalcin 643de78e4feSLisandro Dalcin PetscFunctionBegin; 644*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, lbuf, 4, NULL, PETSC_LONG)); 645*5f80ce2aSJacob Faibussowitsch if (byteSwap) CHKERRQ(PetscByteSwap(lbuf, PETSC_LONG, 4)); 646698a79b9SLisandro Dalcin for (i = 0; i < 4; ++i) count[i] = lbuf[i]; 647*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshEntitiesCreate(count, &mesh->entities)); 648de78e4feSLisandro Dalcin for (dim = 0; dim < 4; ++dim) { 649730356f6SLisandro Dalcin for (index = 0; index < count[dim]; ++index) { 650*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, &eid, 1, NULL, PETSC_ENUM)); 651*5f80ce2aSJacob Faibussowitsch if (byteSwap) CHKERRQ(PetscByteSwap(&eid, PETSC_ENUM, 1)); 652*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshEntitiesAdd(mesh->entities, (PetscInt)index, dim, eid, &entity)); 653*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, entity->bbox, 6, NULL, PETSC_DOUBLE)); 654*5f80ce2aSJacob Faibussowitsch if (byteSwap) CHKERRQ(PetscByteSwap(entity->bbox, PETSC_DOUBLE, 6)); 655*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, &num, 1, NULL, PETSC_LONG)); 656*5f80ce2aSJacob Faibussowitsch if (byteSwap) CHKERRQ(PetscByteSwap(&num, PETSC_LONG, 1)); 657*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshBufferGet(gmsh, num, sizeof(int), &ibuf)); 658*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, ibuf, num, NULL, PETSC_ENUM)); 659*5f80ce2aSJacob Faibussowitsch if (byteSwap) CHKERRQ(PetscByteSwap(ibuf, PETSC_ENUM, num)); 660de78e4feSLisandro Dalcin entity->numTags = numTags = (int) PetscMin(num, 4); 661de78e4feSLisandro Dalcin for (t = 0; t < numTags; ++t) entity->tags[t] = ibuf[t]; 662de78e4feSLisandro Dalcin if (dim == 0) continue; 663*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, &num, 1, NULL, PETSC_LONG)); 664*5f80ce2aSJacob Faibussowitsch if (byteSwap) CHKERRQ(PetscByteSwap(&num, PETSC_LONG, 1)); 665*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshBufferGet(gmsh, num, sizeof(int), &ibuf)); 666*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, ibuf, num, NULL, PETSC_ENUM)); 667*5f80ce2aSJacob Faibussowitsch if (byteSwap) CHKERRQ(PetscByteSwap(ibuf, PETSC_ENUM, num)); 668de78e4feSLisandro Dalcin } 669de78e4feSLisandro Dalcin } 670de78e4feSLisandro Dalcin PetscFunctionReturn(0); 671de78e4feSLisandro Dalcin } 672de78e4feSLisandro Dalcin 673de78e4feSLisandro Dalcin /* 674de78e4feSLisandro Dalcin $Nodes 675de78e4feSLisandro Dalcin numEntityBlocks(unsigned long) numNodes(unsigned long) 676de78e4feSLisandro Dalcin tagEntity(int) dimEntity(int) typeNode(int) numNodes(unsigned long) 677de78e4feSLisandro Dalcin tag(int) x(double) y(double) z(double) 678de78e4feSLisandro Dalcin ... 679de78e4feSLisandro Dalcin ... 680de78e4feSLisandro Dalcin $EndNodes 681de78e4feSLisandro Dalcin */ 6820598e1a2SLisandro Dalcin static PetscErrorCode GmshReadNodes_v40(GmshFile *gmsh, GmshMesh *mesh) 683de78e4feSLisandro Dalcin { 684698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 685698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 6860598e1a2SLisandro Dalcin long block, node, n, numEntityBlocks, numTotalNodes, numNodes; 687de78e4feSLisandro Dalcin int info[3], nid; 6880598e1a2SLisandro Dalcin GmshNodes *nodes; 689de78e4feSLisandro Dalcin 690de78e4feSLisandro Dalcin PetscFunctionBegin; 691*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, &numEntityBlocks, 1, NULL, PETSC_LONG)); 692*5f80ce2aSJacob Faibussowitsch if (byteSwap) CHKERRQ(PetscByteSwap(&numEntityBlocks, PETSC_LONG, 1)); 693*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, &numTotalNodes, 1, NULL, PETSC_LONG)); 694*5f80ce2aSJacob Faibussowitsch if (byteSwap) CHKERRQ(PetscByteSwap(&numTotalNodes, PETSC_LONG, 1)); 695*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshNodesCreate(numTotalNodes, &nodes)); 6960598e1a2SLisandro Dalcin mesh->numNodes = numTotalNodes; 6970598e1a2SLisandro Dalcin mesh->nodelist = nodes; 6980598e1a2SLisandro Dalcin for (n = 0, block = 0; block < numEntityBlocks; ++block) { 699*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, info, 3, NULL, PETSC_ENUM)); 700*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, &numNodes, 1, NULL, PETSC_LONG)); 701*5f80ce2aSJacob Faibussowitsch if (byteSwap) CHKERRQ(PetscByteSwap(&numNodes, PETSC_LONG, 1)); 702698a79b9SLisandro Dalcin if (gmsh->binary) { 703277f51e8SBarry Smith size_t nbytes = sizeof(int) + 3*sizeof(double); 704277f51e8SBarry Smith char *cbuf = NULL; /* dummy value to prevent warning from compiler about possible unitilized value */ 705*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshBufferGet(gmsh, numNodes, nbytes, &cbuf)); 706*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, cbuf, numNodes*nbytes, NULL, PETSC_CHAR)); 7070598e1a2SLisandro Dalcin for (node = 0; node < numNodes; ++node, ++n) { 708de78e4feSLisandro Dalcin char *cnid = cbuf + node*nbytes, *cxyz = cnid + sizeof(int); 7090598e1a2SLisandro Dalcin double *xyz = nodes->xyz + n*3; 710*5f80ce2aSJacob Faibussowitsch if (!PetscBinaryBigEndian()) CHKERRQ(PetscByteSwap(cnid, PETSC_ENUM, 1)); 711*5f80ce2aSJacob Faibussowitsch if (!PetscBinaryBigEndian()) CHKERRQ(PetscByteSwap(cxyz, PETSC_DOUBLE, 3)); 712*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMemcpy(&nid, cnid, sizeof(int))); 713*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMemcpy(xyz, cxyz, 3*sizeof(double))); 714*5f80ce2aSJacob Faibussowitsch if (byteSwap) CHKERRQ(PetscByteSwap(&nid, PETSC_ENUM, 1)); 715*5f80ce2aSJacob Faibussowitsch if (byteSwap) CHKERRQ(PetscByteSwap(xyz, PETSC_DOUBLE, 3)); 7160598e1a2SLisandro Dalcin nodes->id[n] = nid; 71781a1af93SMatthew G. Knepley nodes->tag[n] = -1; 718de78e4feSLisandro Dalcin } 719de78e4feSLisandro Dalcin } else { 7200598e1a2SLisandro Dalcin for (node = 0; node < numNodes; ++node, ++n) { 7210598e1a2SLisandro Dalcin double *xyz = nodes->xyz + n*3; 722*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM)); 723*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE)); 724*5f80ce2aSJacob Faibussowitsch if (byteSwap) CHKERRQ(PetscByteSwap(&nid, PETSC_ENUM, 1)); 725*5f80ce2aSJacob Faibussowitsch if (byteSwap) CHKERRQ(PetscByteSwap(xyz, PETSC_DOUBLE, 3)); 7260598e1a2SLisandro Dalcin nodes->id[n] = nid; 72781a1af93SMatthew G. Knepley nodes->tag[n] = -1; 728de78e4feSLisandro Dalcin } 729de78e4feSLisandro Dalcin } 730de78e4feSLisandro Dalcin } 731de78e4feSLisandro Dalcin PetscFunctionReturn(0); 732de78e4feSLisandro Dalcin } 733de78e4feSLisandro Dalcin 734de78e4feSLisandro Dalcin /* 735de78e4feSLisandro Dalcin $Elements 736de78e4feSLisandro Dalcin numEntityBlocks(unsigned long) numElements(unsigned long) 737de78e4feSLisandro Dalcin tagEntity(int) dimEntity(int) typeEle(int) numElements(unsigned long) 738de78e4feSLisandro Dalcin tag(int) numVert[...](int) 739de78e4feSLisandro Dalcin ... 740de78e4feSLisandro Dalcin ... 741de78e4feSLisandro Dalcin $EndElements 742de78e4feSLisandro Dalcin */ 7430598e1a2SLisandro Dalcin static PetscErrorCode GmshReadElements_v40(GmshFile *gmsh, GmshMesh *mesh) 744de78e4feSLisandro Dalcin { 745698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 746698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 747de78e4feSLisandro Dalcin long c, block, numEntityBlocks, numTotalElements, elem, numElements; 748de78e4feSLisandro Dalcin int p, info[3], *ibuf = NULL; 7490598e1a2SLisandro Dalcin int eid, dim, cellType, numVerts, numNodes, numTags; 750a5ba3d71SLisandro Dalcin GmshEntity *entity = NULL; 751de78e4feSLisandro Dalcin GmshElement *elements; 7520598e1a2SLisandro Dalcin PetscInt *nodeMap = gmsh->nodeMap; 753de78e4feSLisandro Dalcin 754de78e4feSLisandro Dalcin PetscFunctionBegin; 755*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, &numEntityBlocks, 1, NULL, PETSC_LONG)); 756*5f80ce2aSJacob Faibussowitsch if (byteSwap) CHKERRQ(PetscByteSwap(&numEntityBlocks, PETSC_LONG, 1)); 757*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, &numTotalElements, 1, NULL, PETSC_LONG)); 758*5f80ce2aSJacob Faibussowitsch if (byteSwap) CHKERRQ(PetscByteSwap(&numTotalElements, PETSC_LONG, 1)); 759*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshElementsCreate(numTotalElements, &elements)); 7600598e1a2SLisandro Dalcin mesh->numElems = numTotalElements; 7610598e1a2SLisandro Dalcin mesh->elements = elements; 762de78e4feSLisandro Dalcin for (c = 0, block = 0; block < numEntityBlocks; ++block) { 763*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, info, 3, NULL, PETSC_ENUM)); 764*5f80ce2aSJacob Faibussowitsch if (byteSwap) CHKERRQ(PetscByteSwap(info, PETSC_ENUM, 3)); 765de78e4feSLisandro Dalcin eid = info[0]; dim = info[1]; cellType = info[2]; 766*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshEntitiesGet(mesh->entities, dim, eid, &entity)); 767*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshCellTypeCheck(cellType)); 7680598e1a2SLisandro Dalcin numVerts = GmshCellMap[cellType].numVerts; 7690598e1a2SLisandro Dalcin numNodes = GmshCellMap[cellType].numNodes; 770730356f6SLisandro Dalcin numTags = entity->numTags; 771*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, &numElements, 1, NULL, PETSC_LONG)); 772*5f80ce2aSJacob Faibussowitsch if (byteSwap) CHKERRQ(PetscByteSwap(&numElements, PETSC_LONG, 1)); 773*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshBufferGet(gmsh, (1+numNodes)*numElements, sizeof(int), &ibuf)); 774*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, ibuf, (1+numNodes)*numElements, NULL, PETSC_ENUM)); 775*5f80ce2aSJacob Faibussowitsch if (byteSwap) CHKERRQ(PetscByteSwap(ibuf, PETSC_ENUM, (1+numNodes)*numElements)); 776de78e4feSLisandro Dalcin for (elem = 0; elem < numElements; ++elem, ++c) { 777de78e4feSLisandro Dalcin GmshElement *element = elements + c; 7780598e1a2SLisandro Dalcin const int *id = ibuf + elem*(1+numNodes), *nodes = id + 1; 7790598e1a2SLisandro Dalcin element->id = id[0]; 780de78e4feSLisandro Dalcin element->dim = dim; 781de78e4feSLisandro Dalcin element->cellType = cellType; 7820598e1a2SLisandro Dalcin element->numVerts = numVerts; 783de78e4feSLisandro Dalcin element->numNodes = numNodes; 784de78e4feSLisandro Dalcin element->numTags = numTags; 785*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes)); 7860598e1a2SLisandro Dalcin for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]]; 7870598e1a2SLisandro Dalcin for (p = 0; p < element->numTags; p++) element->tags[p] = entity->tags[p]; 788de78e4feSLisandro Dalcin } 789de78e4feSLisandro Dalcin } 790698a79b9SLisandro Dalcin PetscFunctionReturn(0); 791698a79b9SLisandro Dalcin } 792698a79b9SLisandro Dalcin 7930598e1a2SLisandro Dalcin static PetscErrorCode GmshReadPeriodic_v40(GmshFile *gmsh, PetscInt periodicMap[]) 794698a79b9SLisandro Dalcin { 795698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 796698a79b9SLisandro Dalcin int fileFormat = gmsh->fileFormat; 797698a79b9SLisandro Dalcin PetscBool binary = gmsh->binary; 798698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 799698a79b9SLisandro Dalcin int numPeriodic, snum, i; 800698a79b9SLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 8010598e1a2SLisandro Dalcin PetscInt *nodeMap = gmsh->nodeMap; 802698a79b9SLisandro Dalcin 803698a79b9SLisandro Dalcin PetscFunctionBegin; 804698a79b9SLisandro Dalcin if (fileFormat == 22 || !binary) { 805*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 806698a79b9SLisandro Dalcin snum = sscanf(line, "%d", &numPeriodic); 8072c71b3e2SJacob Faibussowitsch PetscCheckFalse(snum != 1,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 808698a79b9SLisandro Dalcin } else { 809*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, &numPeriodic, 1, NULL, PETSC_ENUM)); 810*5f80ce2aSJacob Faibussowitsch if (byteSwap) CHKERRQ(PetscByteSwap(&numPeriodic, PETSC_ENUM, 1)); 811698a79b9SLisandro Dalcin } 812698a79b9SLisandro Dalcin for (i = 0; i < numPeriodic; i++) { 8139dddd249SSatish Balay int ibuf[3], correspondingDim = -1, correspondingTag = -1, primaryTag = -1, correspondingNode, primaryNode; 814698a79b9SLisandro Dalcin long j, nNodes; 815698a79b9SLisandro Dalcin double affine[16]; 816698a79b9SLisandro Dalcin 817698a79b9SLisandro Dalcin if (fileFormat == 22 || !binary) { 818*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, line, 3, NULL, PETSC_STRING)); 8199dddd249SSatish Balay snum = sscanf(line, "%d %d %d", &correspondingDim, &correspondingTag, &primaryTag); 8202c71b3e2SJacob Faibussowitsch PetscCheckFalse(snum != 3,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 821698a79b9SLisandro Dalcin } else { 822*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM)); 823*5f80ce2aSJacob Faibussowitsch if (byteSwap) CHKERRQ(PetscByteSwap(ibuf, PETSC_ENUM, 3)); 8249dddd249SSatish Balay correspondingDim = ibuf[0]; correspondingTag = ibuf[1]; primaryTag = ibuf[2]; 825698a79b9SLisandro Dalcin } 8269dddd249SSatish Balay (void)correspondingDim; (void)correspondingTag; (void)primaryTag; /* unused */ 827698a79b9SLisandro Dalcin 828698a79b9SLisandro Dalcin if (fileFormat == 22 || !binary) { 829*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 830698a79b9SLisandro Dalcin snum = sscanf(line, "%ld", &nNodes); 8314c500f23SPierre Jolivet if (snum != 1) { /* discard transformation and try again */ 832*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, line, -PETSC_MAX_PATH_LEN, NULL, PETSC_STRING)); 833*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 834698a79b9SLisandro Dalcin snum = sscanf(line, "%ld", &nNodes); 8352c71b3e2SJacob Faibussowitsch PetscCheckFalse(snum != 1,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 836698a79b9SLisandro Dalcin } 837698a79b9SLisandro Dalcin } else { 838*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, &nNodes, 1, NULL, PETSC_LONG)); 839*5f80ce2aSJacob Faibussowitsch if (byteSwap) CHKERRQ(PetscByteSwap(&nNodes, PETSC_LONG, 1)); 8404c500f23SPierre Jolivet if (nNodes == -1) { /* discard transformation and try again */ 841*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, affine, 16, NULL, PETSC_DOUBLE)); 842*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, &nNodes, 1, NULL, PETSC_LONG)); 843*5f80ce2aSJacob Faibussowitsch if (byteSwap) CHKERRQ(PetscByteSwap(&nNodes, PETSC_LONG, 1)); 844698a79b9SLisandro Dalcin } 845698a79b9SLisandro Dalcin } 846698a79b9SLisandro Dalcin 847698a79b9SLisandro Dalcin for (j = 0; j < nNodes; j++) { 848698a79b9SLisandro Dalcin if (fileFormat == 22 || !binary) { 849*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, line, 2, NULL, PETSC_STRING)); 8509dddd249SSatish Balay snum = sscanf(line, "%d %d", &correspondingNode, &primaryNode); 8512c71b3e2SJacob Faibussowitsch PetscCheckFalse(snum != 2,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 852698a79b9SLisandro Dalcin } else { 853*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRead(viewer, ibuf, 2, NULL, PETSC_ENUM)); 854*5f80ce2aSJacob Faibussowitsch if (byteSwap) CHKERRQ(PetscByteSwap(ibuf, PETSC_ENUM, 2)); 8559dddd249SSatish Balay correspondingNode = ibuf[0]; primaryNode = ibuf[1]; 856698a79b9SLisandro Dalcin } 8579dddd249SSatish Balay correspondingNode = (int) nodeMap[correspondingNode]; 8589dddd249SSatish Balay primaryNode = (int) nodeMap[primaryNode]; 8599dddd249SSatish Balay periodicMap[correspondingNode] = primaryNode; 860698a79b9SLisandro Dalcin } 861698a79b9SLisandro Dalcin } 862698a79b9SLisandro Dalcin PetscFunctionReturn(0); 863698a79b9SLisandro Dalcin } 864698a79b9SLisandro Dalcin 8650598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 866698a79b9SLisandro Dalcin $Entities 867698a79b9SLisandro Dalcin numPoints(size_t) numCurves(size_t) 868698a79b9SLisandro Dalcin numSurfaces(size_t) numVolumes(size_t) 869698a79b9SLisandro Dalcin pointTag(int) X(double) Y(double) Z(double) 870698a79b9SLisandro Dalcin numPhysicalTags(size_t) physicalTag(int) ... 871698a79b9SLisandro Dalcin ... 872698a79b9SLisandro Dalcin curveTag(int) minX(double) minY(double) minZ(double) 873698a79b9SLisandro Dalcin maxX(double) maxY(double) maxZ(double) 874698a79b9SLisandro Dalcin numPhysicalTags(size_t) physicalTag(int) ... 875698a79b9SLisandro Dalcin numBoundingPoints(size_t) pointTag(int) ... 876698a79b9SLisandro Dalcin ... 877698a79b9SLisandro Dalcin surfaceTag(int) minX(double) minY(double) minZ(double) 878698a79b9SLisandro Dalcin maxX(double) maxY(double) maxZ(double) 879698a79b9SLisandro Dalcin numPhysicalTags(size_t) physicalTag(int) ... 880698a79b9SLisandro Dalcin numBoundingCurves(size_t) curveTag(int) ... 881698a79b9SLisandro Dalcin ... 882698a79b9SLisandro Dalcin volumeTag(int) minX(double) minY(double) minZ(double) 883698a79b9SLisandro Dalcin maxX(double) maxY(double) maxZ(double) 884698a79b9SLisandro Dalcin numPhysicalTags(size_t) physicalTag(int) ... 885698a79b9SLisandro Dalcin numBoundngSurfaces(size_t) surfaceTag(int) ... 886698a79b9SLisandro Dalcin ... 887698a79b9SLisandro Dalcin $EndEntities 888698a79b9SLisandro Dalcin */ 8890598e1a2SLisandro Dalcin static PetscErrorCode GmshReadEntities_v41(GmshFile *gmsh, GmshMesh *mesh) 890698a79b9SLisandro Dalcin { 891698a79b9SLisandro Dalcin PetscInt count[4], index, numTags, i; 892698a79b9SLisandro Dalcin int dim, eid, *tags = NULL; 893698a79b9SLisandro Dalcin GmshEntity *entity = NULL; 894698a79b9SLisandro Dalcin 895698a79b9SLisandro Dalcin PetscFunctionBegin; 896*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadSize(gmsh, count, 4)); 897*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshEntitiesCreate(count, &mesh->entities)); 898698a79b9SLisandro Dalcin for (dim = 0; dim < 4; ++dim) { 899698a79b9SLisandro Dalcin for (index = 0; index < count[dim]; ++index) { 900*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadInt(gmsh, &eid, 1)); 901*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshEntitiesAdd(mesh->entities, (PetscInt)index, dim, eid, &entity)); 902*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadDouble(gmsh, entity->bbox, (dim == 0) ? 3 : 6)); 903*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadSize(gmsh, &numTags, 1)); 904*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshBufferGet(gmsh, numTags, sizeof(int), &tags)); 905*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadInt(gmsh, tags, numTags)); 906698a79b9SLisandro Dalcin entity->numTags = PetscMin(numTags, 4); 907698a79b9SLisandro Dalcin for (i = 0; i < entity->numTags; ++i) entity->tags[i] = tags[i]; 908698a79b9SLisandro Dalcin if (dim == 0) continue; 909*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadSize(gmsh, &numTags, 1)); 910*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshBufferGet(gmsh, numTags, sizeof(int), &tags)); 911*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadInt(gmsh, tags, numTags)); 91281a1af93SMatthew G. Knepley /* Currently, we do not save the ids for the bounding entities */ 913698a79b9SLisandro Dalcin } 914698a79b9SLisandro Dalcin } 915698a79b9SLisandro Dalcin PetscFunctionReturn(0); 916698a79b9SLisandro Dalcin } 917698a79b9SLisandro Dalcin 91833a088b6SMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 919698a79b9SLisandro Dalcin $Nodes 920698a79b9SLisandro Dalcin numEntityBlocks(size_t) numNodes(size_t) 921698a79b9SLisandro Dalcin minNodeTag(size_t) maxNodeTag(size_t) 922698a79b9SLisandro Dalcin entityDim(int) entityTag(int) parametric(int; 0 or 1) numNodesBlock(size_t) 923698a79b9SLisandro Dalcin nodeTag(size_t) 924698a79b9SLisandro Dalcin ... 925698a79b9SLisandro Dalcin x(double) y(double) z(double) 926698a79b9SLisandro Dalcin < u(double; if parametric and entityDim = 1 or entityDim = 2) > 927698a79b9SLisandro Dalcin < v(double; if parametric and entityDim = 2) > 928698a79b9SLisandro Dalcin ... 929698a79b9SLisandro Dalcin ... 930698a79b9SLisandro Dalcin $EndNodes 931698a79b9SLisandro Dalcin */ 9320598e1a2SLisandro Dalcin static PetscErrorCode GmshReadNodes_v41(GmshFile *gmsh, GmshMesh *mesh) 933698a79b9SLisandro Dalcin { 93481a1af93SMatthew G. Knepley int info[3], dim, eid, parametric; 93581a1af93SMatthew G. Knepley PetscInt sizes[4], numEntityBlocks, numTags, numNodes, numNodesBlock = 0, block, node, n; 93681a1af93SMatthew G. Knepley GmshEntity *entity = NULL; 9370598e1a2SLisandro Dalcin GmshNodes *nodes; 938698a79b9SLisandro Dalcin 939698a79b9SLisandro Dalcin PetscFunctionBegin; 940*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadSize(gmsh, sizes, 4)); 9410598e1a2SLisandro Dalcin numEntityBlocks = sizes[0]; numNodes = sizes[1]; 942*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshNodesCreate(numNodes, &nodes)); 9430598e1a2SLisandro Dalcin mesh->numNodes = numNodes; 9440598e1a2SLisandro Dalcin mesh->nodelist = nodes; 945698a79b9SLisandro Dalcin for (block = 0, node = 0; block < numEntityBlocks; ++block, node += numNodesBlock) { 946*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadInt(gmsh, info, 3)); 94781a1af93SMatthew G. Knepley dim = info[0]; eid = info[1]; parametric = info[2]; 948*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshEntitiesGet(mesh->entities, dim, eid, &entity)); 94981a1af93SMatthew G. Knepley numTags = PetscMin(1, entity->numTags); 95081a1af93SMatthew G. Knepley if (entity->numTags > 1) PetscInfo(NULL, "Entity %d has more than %d physical tags, assigning only the first to nodes", eid, 1); 95181a1af93SMatthew G. Knepley PetscCheck(!parametric, PETSC_COMM_SELF, PETSC_ERR_SUP, "Parametric coordinates not supported"); 952*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadSize(gmsh, &numNodesBlock, 1)); 953*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadSize(gmsh, nodes->id+node, numNodesBlock)); 954*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadDouble(gmsh, nodes->xyz+node*3, numNodesBlock*3)); 95581a1af93SMatthew G. Knepley for (n = 0; n < numNodesBlock; ++n) nodes->tag[node+n] = numTags ? entity->tags[0] : -1; 956698a79b9SLisandro Dalcin } 9570598e1a2SLisandro Dalcin gmsh->nodeStart = sizes[2]; 9580598e1a2SLisandro Dalcin gmsh->nodeEnd = sizes[3]+1; 959698a79b9SLisandro Dalcin PetscFunctionReturn(0); 960698a79b9SLisandro Dalcin } 961698a79b9SLisandro Dalcin 96233a088b6SMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 963698a79b9SLisandro Dalcin $Elements 964698a79b9SLisandro Dalcin numEntityBlocks(size_t) numElements(size_t) 965698a79b9SLisandro Dalcin minElementTag(size_t) maxElementTag(size_t) 966698a79b9SLisandro Dalcin entityDim(int) entityTag(int) elementType(int; see below) numElementsBlock(size_t) 967698a79b9SLisandro Dalcin elementTag(size_t) nodeTag(size_t) ... 968698a79b9SLisandro Dalcin ... 969698a79b9SLisandro Dalcin ... 970698a79b9SLisandro Dalcin $EndElements 971698a79b9SLisandro Dalcin */ 9720598e1a2SLisandro Dalcin static PetscErrorCode GmshReadElements_v41(GmshFile *gmsh, GmshMesh *mesh) 973698a79b9SLisandro Dalcin { 9740598e1a2SLisandro Dalcin int info[3], eid, dim, cellType; 9750598e1a2SLisandro Dalcin PetscInt sizes[4], *ibuf = NULL, numEntityBlocks, numElements, numBlockElements, numVerts, numNodes, numTags, block, elem, c, p; 976698a79b9SLisandro Dalcin GmshEntity *entity = NULL; 977698a79b9SLisandro Dalcin GmshElement *elements; 9780598e1a2SLisandro Dalcin PetscInt *nodeMap = gmsh->nodeMap; 979698a79b9SLisandro Dalcin 980698a79b9SLisandro Dalcin PetscFunctionBegin; 981*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadSize(gmsh, sizes, 4)); 982698a79b9SLisandro Dalcin numEntityBlocks = sizes[0]; numElements = sizes[1]; 983*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshElementsCreate(numElements, &elements)); 9840598e1a2SLisandro Dalcin mesh->numElems = numElements; 9850598e1a2SLisandro Dalcin mesh->elements = elements; 986698a79b9SLisandro Dalcin for (c = 0, block = 0; block < numEntityBlocks; ++block) { 987*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadInt(gmsh, info, 3)); 988698a79b9SLisandro Dalcin dim = info[0]; eid = info[1]; cellType = info[2]; 989*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshEntitiesGet(mesh->entities, dim, eid, &entity)); 990*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshCellTypeCheck(cellType)); 9910598e1a2SLisandro Dalcin numVerts = GmshCellMap[cellType].numVerts; 9920598e1a2SLisandro Dalcin numNodes = GmshCellMap[cellType].numNodes; 99381a1af93SMatthew G. Knepley numTags = PetscMin(4, entity->numTags); 99481a1af93SMatthew G. Knepley if (entity->numTags > 4) PetscInfo(NULL, "Entity %d has more then %d physical tags, assigning only the first to elements", eid, 4); 995*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadSize(gmsh, &numBlockElements, 1)); 996*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshBufferGet(gmsh, (1+numNodes)*numBlockElements, sizeof(PetscInt), &ibuf)); 997*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadSize(gmsh, ibuf, (1+numNodes)*numBlockElements)); 998698a79b9SLisandro Dalcin for (elem = 0; elem < numBlockElements; ++elem, ++c) { 999698a79b9SLisandro Dalcin GmshElement *element = elements + c; 10000598e1a2SLisandro Dalcin const PetscInt *id = ibuf + elem*(1+numNodes), *nodes = id + 1; 1001698a79b9SLisandro Dalcin element->id = id[0]; 1002698a79b9SLisandro Dalcin element->dim = dim; 1003698a79b9SLisandro Dalcin element->cellType = cellType; 10040598e1a2SLisandro Dalcin element->numVerts = numVerts; 1005698a79b9SLisandro Dalcin element->numNodes = numNodes; 1006698a79b9SLisandro Dalcin element->numTags = numTags; 1007*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes)); 10080598e1a2SLisandro Dalcin for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]]; 10090598e1a2SLisandro Dalcin for (p = 0; p < element->numTags; p++) element->tags[p] = entity->tags[p]; 1010698a79b9SLisandro Dalcin } 1011698a79b9SLisandro Dalcin } 1012698a79b9SLisandro Dalcin PetscFunctionReturn(0); 1013698a79b9SLisandro Dalcin } 1014698a79b9SLisandro Dalcin 10150598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 1016698a79b9SLisandro Dalcin $Periodic 1017698a79b9SLisandro Dalcin numPeriodicLinks(size_t) 10189dddd249SSatish Balay entityDim(int) entityTag(int) entityTagPrimary(int) 1019698a79b9SLisandro Dalcin numAffine(size_t) value(double) ... 1020698a79b9SLisandro Dalcin numCorrespondingNodes(size_t) 10219dddd249SSatish Balay nodeTag(size_t) nodeTagPrimary(size_t) 1022698a79b9SLisandro Dalcin ... 1023698a79b9SLisandro Dalcin ... 1024698a79b9SLisandro Dalcin $EndPeriodic 1025698a79b9SLisandro Dalcin */ 10260598e1a2SLisandro Dalcin static PetscErrorCode GmshReadPeriodic_v41(GmshFile *gmsh, PetscInt periodicMap[]) 1027698a79b9SLisandro Dalcin { 1028698a79b9SLisandro Dalcin int info[3]; 1029698a79b9SLisandro Dalcin double dbuf[16]; 10300598e1a2SLisandro Dalcin PetscInt numPeriodicLinks, numAffine, numCorrespondingNodes, *nodeTags = NULL, link, node; 10310598e1a2SLisandro Dalcin PetscInt *nodeMap = gmsh->nodeMap; 1032698a79b9SLisandro Dalcin 1033698a79b9SLisandro Dalcin PetscFunctionBegin; 1034*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadSize(gmsh, &numPeriodicLinks, 1)); 1035698a79b9SLisandro Dalcin for (link = 0; link < numPeriodicLinks; ++link) { 1036*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadInt(gmsh, info, 3)); 1037*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadSize(gmsh, &numAffine, 1)); 1038*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadDouble(gmsh, dbuf, numAffine)); 1039*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadSize(gmsh, &numCorrespondingNodes, 1)); 1040*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshBufferGet(gmsh, numCorrespondingNodes, sizeof(PetscInt), &nodeTags)); 1041*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadSize(gmsh, nodeTags, numCorrespondingNodes*2)); 1042698a79b9SLisandro Dalcin for (node = 0; node < numCorrespondingNodes; ++node) { 10439dddd249SSatish Balay PetscInt correspondingNode = nodeMap[nodeTags[node*2+0]]; 10449dddd249SSatish Balay PetscInt primaryNode = nodeMap[nodeTags[node*2+1]]; 10459dddd249SSatish Balay periodicMap[correspondingNode] = primaryNode; 1046698a79b9SLisandro Dalcin } 1047698a79b9SLisandro Dalcin } 1048698a79b9SLisandro Dalcin PetscFunctionReturn(0); 1049698a79b9SLisandro Dalcin } 1050698a79b9SLisandro Dalcin 10510598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 1052d6689ca9SLisandro Dalcin $MeshFormat // same as MSH version 2 1053d6689ca9SLisandro Dalcin version(ASCII double; currently 4.1) 1054d6689ca9SLisandro Dalcin file-type(ASCII int; 0 for ASCII mode, 1 for binary mode) 1055d6689ca9SLisandro Dalcin data-size(ASCII int; sizeof(size_t)) 1056d6689ca9SLisandro Dalcin < int with value one; only in binary mode, to detect endianness > 1057d6689ca9SLisandro Dalcin $EndMeshFormat 1058d6689ca9SLisandro Dalcin */ 10590598e1a2SLisandro Dalcin static PetscErrorCode GmshReadMeshFormat(GmshFile *gmsh) 1060698a79b9SLisandro Dalcin { 1061698a79b9SLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 1062698a79b9SLisandro Dalcin int snum, fileType, fileFormat, dataSize, checkEndian; 1063698a79b9SLisandro Dalcin float version; 1064698a79b9SLisandro Dalcin 1065698a79b9SLisandro Dalcin PetscFunctionBegin; 1066*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadString(gmsh, line, 3)); 1067698a79b9SLisandro Dalcin snum = sscanf(line, "%f %d %d", &version, &fileType, &dataSize); 10682c71b3e2SJacob Faibussowitsch PetscCheckFalse(snum != 3,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line); 10692c71b3e2SJacob Faibussowitsch PetscCheckFalse(version < 2.2,PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at least 2.2", (double)version); 10702c71b3e2SJacob Faibussowitsch PetscCheckFalse((int)version == 3,PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f not supported", (double)version); 10712c71b3e2SJacob Faibussowitsch PetscCheckFalse(version > 4.1,PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at most 4.1", (double)version); 10722c71b3e2SJacob Faibussowitsch PetscCheckFalse(gmsh->binary && !fileType,PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Viewer is binary but Gmsh file is ASCII"); 10732c71b3e2SJacob Faibussowitsch PetscCheckFalse(!gmsh->binary && fileType,PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Viewer is ASCII but Gmsh file is binary"); 1074af7a0b9fSSatish Balay fileFormat = (int)roundf(version*10); 10752c71b3e2SJacob Faibussowitsch PetscCheckFalse(fileFormat <= 40 && dataSize != sizeof(double),PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Data size %d is not valid for a Gmsh file", dataSize); 10762c71b3e2SJacob Faibussowitsch PetscCheckFalse(fileFormat >= 41 && dataSize != sizeof(int) && dataSize != sizeof(PetscInt64),PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Data size %d is not valid for a Gmsh file", dataSize); 1077698a79b9SLisandro Dalcin gmsh->fileFormat = fileFormat; 1078698a79b9SLisandro Dalcin gmsh->dataSize = dataSize; 1079698a79b9SLisandro Dalcin gmsh->byteSwap = PETSC_FALSE; 1080698a79b9SLisandro Dalcin if (gmsh->binary) { 1081*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadInt(gmsh, &checkEndian, 1)); 1082698a79b9SLisandro Dalcin if (checkEndian != 1) { 1083*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscByteSwap(&checkEndian, PETSC_ENUM, 1)); 10842c71b3e2SJacob Faibussowitsch PetscCheckFalse(checkEndian != 1,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to detect endianness in Gmsh file header: %s", line); 1085698a79b9SLisandro Dalcin gmsh->byteSwap = PETSC_TRUE; 1086698a79b9SLisandro Dalcin } 1087698a79b9SLisandro Dalcin } 1088698a79b9SLisandro Dalcin PetscFunctionReturn(0); 1089698a79b9SLisandro Dalcin } 1090698a79b9SLisandro Dalcin 10911f643af3SLisandro Dalcin /* 10921f643af3SLisandro Dalcin PhysicalNames 10931f643af3SLisandro Dalcin numPhysicalNames(ASCII int) 10941f643af3SLisandro Dalcin dimension(ASCII int) physicalTag(ASCII int) "name"(127 characters max) 10951f643af3SLisandro Dalcin ... 10961f643af3SLisandro Dalcin $EndPhysicalNames 10971f643af3SLisandro Dalcin */ 1098a45dabc8SMatthew G. Knepley static PetscErrorCode GmshReadPhysicalNames(GmshFile *gmsh, GmshMesh *mesh) 1099698a79b9SLisandro Dalcin { 11001f643af3SLisandro Dalcin char line[PETSC_MAX_PATH_LEN], name[128+2], *p, *q; 1101a45dabc8SMatthew G. Knepley int snum, region, dim, tag; 1102698a79b9SLisandro Dalcin 1103698a79b9SLisandro Dalcin PetscFunctionBegin; 1104*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadString(gmsh, line, 1)); 1105a45dabc8SMatthew G. Knepley snum = sscanf(line, "%d", ®ion); 1106a45dabc8SMatthew G. Knepley mesh->numRegions = region; 11072c71b3e2SJacob Faibussowitsch PetscCheckFalse(snum != 1,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 1108*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(mesh->numRegions, &mesh->regionTags, mesh->numRegions, &mesh->regionNames)); 1109a45dabc8SMatthew G. Knepley for (region = 0; region < mesh->numRegions; ++region) { 1110*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadString(gmsh, line, 2)); 11111f643af3SLisandro Dalcin snum = sscanf(line, "%d %d", &dim, &tag); 11122c71b3e2SJacob Faibussowitsch PetscCheckFalse(snum != 2,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 1113*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadString(gmsh, line, -(PetscInt)sizeof(line))); 1114*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrchr(line, '"', &p)); 11152c71b3e2SJacob Faibussowitsch PetscCheckFalse(!p,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 1116*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrrchr(line, '"', &q)); 11172c71b3e2SJacob Faibussowitsch PetscCheckFalse(q == p,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 1118*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrncpy(name, p+1, (size_t)(q-p-1))); 1119a45dabc8SMatthew G. Knepley mesh->regionTags[region] = tag; 1120*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrallocpy(name, &mesh->regionNames[region])); 1121698a79b9SLisandro Dalcin } 1122de78e4feSLisandro Dalcin PetscFunctionReturn(0); 1123de78e4feSLisandro Dalcin } 1124de78e4feSLisandro Dalcin 11250598e1a2SLisandro Dalcin static PetscErrorCode GmshReadEntities(GmshFile *gmsh, GmshMesh *mesh) 112696ca5757SLisandro Dalcin { 11270598e1a2SLisandro Dalcin PetscFunctionBegin; 11280598e1a2SLisandro Dalcin switch (gmsh->fileFormat) { 1129*5f80ce2aSJacob Faibussowitsch case 41: CHKERRQ(GmshReadEntities_v41(gmsh, mesh)); break; 1130*5f80ce2aSJacob Faibussowitsch default: CHKERRQ(GmshReadEntities_v40(gmsh, mesh)); break; 113196ca5757SLisandro Dalcin } 11320598e1a2SLisandro Dalcin PetscFunctionReturn(0); 11330598e1a2SLisandro Dalcin } 11340598e1a2SLisandro Dalcin 11350598e1a2SLisandro Dalcin static PetscErrorCode GmshReadNodes(GmshFile *gmsh, GmshMesh *mesh) 11360598e1a2SLisandro Dalcin { 11370598e1a2SLisandro Dalcin PetscFunctionBegin; 11380598e1a2SLisandro Dalcin switch (gmsh->fileFormat) { 1139*5f80ce2aSJacob Faibussowitsch case 41: CHKERRQ(GmshReadNodes_v41(gmsh, mesh)); break; 1140*5f80ce2aSJacob Faibussowitsch case 40: CHKERRQ(GmshReadNodes_v40(gmsh, mesh)); break; 1141*5f80ce2aSJacob Faibussowitsch default: CHKERRQ(GmshReadNodes_v22(gmsh, mesh)); break; 11420598e1a2SLisandro Dalcin } 11430598e1a2SLisandro Dalcin 11440598e1a2SLisandro Dalcin { /* Gmsh v2.2/v4.0 does not provide min/max node tags */ 11450598e1a2SLisandro Dalcin if (mesh->numNodes > 0 && gmsh->nodeEnd >= gmsh->nodeStart) { 11460598e1a2SLisandro Dalcin PetscInt tagMin = PETSC_MAX_INT, tagMax = PETSC_MIN_INT, n; 11470598e1a2SLisandro Dalcin GmshNodes *nodes = mesh->nodelist; 11480598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) { 11490598e1a2SLisandro Dalcin const PetscInt tag = nodes->id[n]; 11500598e1a2SLisandro Dalcin tagMin = PetscMin(tag, tagMin); 11510598e1a2SLisandro Dalcin tagMax = PetscMax(tag, tagMax); 11520598e1a2SLisandro Dalcin } 11530598e1a2SLisandro Dalcin gmsh->nodeStart = tagMin; 11540598e1a2SLisandro Dalcin gmsh->nodeEnd = tagMax+1; 11550598e1a2SLisandro Dalcin } 11560598e1a2SLisandro Dalcin } 11570598e1a2SLisandro Dalcin 11580598e1a2SLisandro Dalcin { /* Support for sparse node tags */ 11590598e1a2SLisandro Dalcin PetscInt n, t; 11600598e1a2SLisandro Dalcin GmshNodes *nodes = mesh->nodelist; 1161*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(gmsh->nodeEnd - gmsh->nodeStart, &gmsh->nbuf)); 11620598e1a2SLisandro Dalcin for (t = 0; t < gmsh->nodeEnd - gmsh->nodeStart; ++t) gmsh->nbuf[t] = PETSC_MIN_INT; 11630598e1a2SLisandro Dalcin gmsh->nodeMap = gmsh->nbuf - gmsh->nodeStart; 11640598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) { 11650598e1a2SLisandro Dalcin const PetscInt tag = nodes->id[n]; 11662c71b3e2SJacob Faibussowitsch PetscCheckFalse(gmsh->nodeMap[tag] >= 0,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Repeated node tag %D", tag); 11670598e1a2SLisandro Dalcin gmsh->nodeMap[tag] = n; 11680598e1a2SLisandro Dalcin } 11690598e1a2SLisandro Dalcin } 11700598e1a2SLisandro Dalcin PetscFunctionReturn(0); 11710598e1a2SLisandro Dalcin } 11720598e1a2SLisandro Dalcin 11730598e1a2SLisandro Dalcin static PetscErrorCode GmshReadElements(GmshFile *gmsh, GmshMesh *mesh) 11740598e1a2SLisandro Dalcin { 11750598e1a2SLisandro Dalcin PetscFunctionBegin; 11760598e1a2SLisandro Dalcin switch (gmsh->fileFormat) { 1177*5f80ce2aSJacob Faibussowitsch case 41: CHKERRQ(GmshReadElements_v41(gmsh, mesh)); break; 1178*5f80ce2aSJacob Faibussowitsch case 40: CHKERRQ(GmshReadElements_v40(gmsh, mesh)); break; 1179*5f80ce2aSJacob Faibussowitsch default: CHKERRQ(GmshReadElements_v22(gmsh, mesh)); break; 11800598e1a2SLisandro Dalcin } 11810598e1a2SLisandro Dalcin 11820598e1a2SLisandro Dalcin { /* Reorder elements by codimension and polytope type */ 11830598e1a2SLisandro Dalcin PetscInt ne = mesh->numElems; 11840598e1a2SLisandro Dalcin GmshElement *elements = mesh->elements; 1185066ea43fSLisandro Dalcin PetscInt keymap[GMSH_NUM_POLYTOPES], nk = 0; 1186066ea43fSLisandro Dalcin PetscInt offset[GMSH_NUM_POLYTOPES+1], e, k; 11870598e1a2SLisandro Dalcin 1188066ea43fSLisandro Dalcin for (k = 0; k < GMSH_NUM_POLYTOPES; ++k) keymap[k] = PETSC_MIN_INT; 1189*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMemzero(offset,sizeof(offset))); 11900598e1a2SLisandro Dalcin 1191066ea43fSLisandro Dalcin keymap[GMSH_TET] = nk++; 1192066ea43fSLisandro Dalcin keymap[GMSH_HEX] = nk++; 1193066ea43fSLisandro Dalcin keymap[GMSH_PRI] = nk++; 1194066ea43fSLisandro Dalcin keymap[GMSH_PYR] = nk++; 1195066ea43fSLisandro Dalcin keymap[GMSH_TRI] = nk++; 1196066ea43fSLisandro Dalcin keymap[GMSH_QUA] = nk++; 1197066ea43fSLisandro Dalcin keymap[GMSH_SEG] = nk++; 1198066ea43fSLisandro Dalcin keymap[GMSH_VTX] = nk++; 11990598e1a2SLisandro Dalcin 1200*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshElementsCreate(mesh->numElems, &mesh->elements)); 12010598e1a2SLisandro Dalcin #define key(eid) keymap[GmshCellMap[elements[(eid)].cellType].polytope] 12020598e1a2SLisandro Dalcin for (e = 0; e < ne; ++e) offset[1+key(e)]++; 12030598e1a2SLisandro Dalcin for (k = 1; k < nk; ++k) offset[k] += offset[k-1]; 12040598e1a2SLisandro Dalcin for (e = 0; e < ne; ++e) mesh->elements[offset[key(e)]++] = elements[e]; 12050598e1a2SLisandro Dalcin #undef key 1206*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshElementsDestroy(&elements)); 1207066ea43fSLisandro Dalcin } 12080598e1a2SLisandro Dalcin 1209066ea43fSLisandro Dalcin { /* Mesh dimension and order */ 1210066ea43fSLisandro Dalcin GmshElement *elem = mesh->numElems ? mesh->elements : NULL; 1211066ea43fSLisandro Dalcin mesh->dim = elem ? GmshCellMap[elem->cellType].dim : 0; 1212066ea43fSLisandro Dalcin mesh->order = elem ? GmshCellMap[elem->cellType].order : 0; 12130598e1a2SLisandro Dalcin } 12140598e1a2SLisandro Dalcin 12150598e1a2SLisandro Dalcin { 12160598e1a2SLisandro Dalcin PetscBT vtx; 12170598e1a2SLisandro Dalcin PetscInt dim = mesh->dim, e, n, v; 12180598e1a2SLisandro Dalcin 1219*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTCreate(mesh->numNodes, &vtx)); 12200598e1a2SLisandro Dalcin 12210598e1a2SLisandro Dalcin /* Compute number of cells and set of vertices */ 12220598e1a2SLisandro Dalcin mesh->numCells = 0; 12230598e1a2SLisandro Dalcin for (e = 0; e < mesh->numElems; ++e) { 12240598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + e; 12250598e1a2SLisandro Dalcin if (elem->dim == dim && dim > 0) mesh->numCells++; 12260598e1a2SLisandro Dalcin for (v = 0; v < elem->numVerts; v++) { 1227*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTSet(vtx, elem->nodes[v])); 12280598e1a2SLisandro Dalcin } 12290598e1a2SLisandro Dalcin } 12300598e1a2SLisandro Dalcin 12310598e1a2SLisandro Dalcin /* Compute numbering for vertices */ 12320598e1a2SLisandro Dalcin mesh->numVerts = 0; 1233*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(mesh->numNodes, &mesh->vertexMap)); 12340598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) 12350598e1a2SLisandro Dalcin mesh->vertexMap[n] = PetscBTLookup(vtx, n) ? mesh->numVerts++ : PETSC_MIN_INT; 12360598e1a2SLisandro Dalcin 1237*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTDestroy(&vtx)); 12380598e1a2SLisandro Dalcin } 12390598e1a2SLisandro Dalcin PetscFunctionReturn(0); 12400598e1a2SLisandro Dalcin } 12410598e1a2SLisandro Dalcin 12420598e1a2SLisandro Dalcin static PetscErrorCode GmshReadPeriodic(GmshFile *gmsh, GmshMesh *mesh) 12430598e1a2SLisandro Dalcin { 12440598e1a2SLisandro Dalcin PetscInt n; 12450598e1a2SLisandro Dalcin 12460598e1a2SLisandro Dalcin PetscFunctionBegin; 1247*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(mesh->numNodes, &mesh->periodMap)); 12480598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) mesh->periodMap[n] = n; 12490598e1a2SLisandro Dalcin switch (gmsh->fileFormat) { 1250*5f80ce2aSJacob Faibussowitsch case 41: CHKERRQ(GmshReadPeriodic_v41(gmsh, mesh->periodMap)); break; 1251*5f80ce2aSJacob Faibussowitsch default: CHKERRQ(GmshReadPeriodic_v40(gmsh, mesh->periodMap)); break; 12520598e1a2SLisandro Dalcin } 12530598e1a2SLisandro Dalcin 12549dddd249SSatish Balay /* Find canonical primary nodes */ 12550598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) 12560598e1a2SLisandro Dalcin while (mesh->periodMap[n] != mesh->periodMap[mesh->periodMap[n]]) 12570598e1a2SLisandro Dalcin mesh->periodMap[n] = mesh->periodMap[mesh->periodMap[n]]; 12580598e1a2SLisandro Dalcin 12599dddd249SSatish Balay /* Renumber vertices (filter out correspondings) */ 12600598e1a2SLisandro Dalcin mesh->numVerts = 0; 12610598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) 12620598e1a2SLisandro Dalcin if (mesh->vertexMap[n] >= 0) /* is vertex */ 12639dddd249SSatish Balay if (mesh->periodMap[n] == n) /* is primary */ 12640598e1a2SLisandro Dalcin mesh->vertexMap[n] = mesh->numVerts++; 12650598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) 12660598e1a2SLisandro Dalcin if (mesh->vertexMap[n] >= 0) /* is vertex */ 12679dddd249SSatish Balay if (mesh->periodMap[n] != n) /* is corresponding */ 12680598e1a2SLisandro Dalcin mesh->vertexMap[n] = mesh->vertexMap[mesh->periodMap[n]]; 12690598e1a2SLisandro Dalcin PetscFunctionReturn(0); 12700598e1a2SLisandro Dalcin } 12710598e1a2SLisandro Dalcin 1272066ea43fSLisandro Dalcin #define DM_POLYTOPE_VERTEX DM_POLYTOPE_POINT 1273066ea43fSLisandro Dalcin #define DM_POLYTOPE_PYRAMID DM_POLYTOPE_UNKNOWN 1274066ea43fSLisandro Dalcin static const DMPolytopeType DMPolytopeMap[] = { 1275066ea43fSLisandro Dalcin /* GMSH_VTX */ DM_POLYTOPE_VERTEX, 1276066ea43fSLisandro Dalcin /* GMSH_SEG */ DM_POLYTOPE_SEGMENT, 1277066ea43fSLisandro Dalcin /* GMSH_TRI */ DM_POLYTOPE_TRIANGLE, 1278066ea43fSLisandro Dalcin /* GMSH_QUA */ DM_POLYTOPE_QUADRILATERAL, 1279066ea43fSLisandro Dalcin /* GMSH_TET */ DM_POLYTOPE_TETRAHEDRON, 1280066ea43fSLisandro Dalcin /* GMSH_HEX */ DM_POLYTOPE_HEXAHEDRON, 1281066ea43fSLisandro Dalcin /* GMSH_PRI */ DM_POLYTOPE_TRI_PRISM, 1282066ea43fSLisandro Dalcin /* GMSH_PYR */ DM_POLYTOPE_PYRAMID, 1283066ea43fSLisandro Dalcin DM_POLYTOPE_UNKNOWN 1284066ea43fSLisandro Dalcin }; 12850598e1a2SLisandro Dalcin 12869fbee547SJacob Faibussowitsch static inline DMPolytopeType DMPolytopeTypeFromGmsh(PetscInt cellType) 12870598e1a2SLisandro Dalcin { 1288066ea43fSLisandro Dalcin return DMPolytopeMap[GmshCellMap[cellType].polytope]; 1289066ea43fSLisandro Dalcin } 1290066ea43fSLisandro Dalcin 1291066ea43fSLisandro Dalcin static PetscErrorCode GmshCreateFE(MPI_Comm comm, const char prefix[], PetscBool isSimplex, PetscBool continuity, PetscDTNodeType nodeType, PetscInt dim, PetscInt Nc, PetscInt k, PetscFE *fem) 1292066ea43fSLisandro Dalcin { 1293066ea43fSLisandro Dalcin DM K; 1294066ea43fSLisandro Dalcin PetscSpace P; 1295066ea43fSLisandro Dalcin PetscDualSpace Q; 1296066ea43fSLisandro Dalcin PetscQuadrature q, fq; 1297066ea43fSLisandro Dalcin PetscBool isTensor = isSimplex ? PETSC_FALSE : PETSC_TRUE; 1298066ea43fSLisandro Dalcin PetscBool endpoint = PETSC_TRUE; 1299066ea43fSLisandro Dalcin char name[32]; 1300066ea43fSLisandro Dalcin 1301066ea43fSLisandro Dalcin PetscFunctionBegin; 1302066ea43fSLisandro Dalcin /* Create space */ 1303*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSpaceCreate(comm, &P)); 1304*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSpaceSetType(P, PETSCSPACEPOLYNOMIAL)); 1305*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSpacePolynomialSetTensor(P, isTensor)); 1306*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSpaceSetNumComponents(P, Nc)); 1307*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSpaceSetNumVariables(P, dim)); 1308*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSpaceSetDegree(P, k, PETSC_DETERMINE)); 1309066ea43fSLisandro Dalcin if (prefix) { 1310*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject) P, prefix)); 1311*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSpaceSetFromOptions(P)); 1312*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject) P, NULL)); 1313*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSpaceGetDegree(P, &k, NULL)); 1314066ea43fSLisandro Dalcin } 1315*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSpaceSetUp(P)); 1316066ea43fSLisandro Dalcin /* Create dual space */ 1317*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceCreate(comm, &Q)); 1318*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceSetType(Q, PETSCDUALSPACELAGRANGE)); 1319*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceLagrangeSetTensor(Q, isTensor)); 1320*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceLagrangeSetContinuity(Q, continuity)); 1321*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceLagrangeSetNodeType(Q, nodeType, endpoint, 0)); 1322*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceSetNumComponents(Q, Nc)); 1323*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceSetOrder(Q, k)); 1324*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateReferenceCell(PETSC_COMM_SELF, DMPolytopeTypeSimpleShape(dim, isSimplex), &K)); 1325*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceSetDM(Q, K)); 1326*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&K)); 1327066ea43fSLisandro Dalcin if (prefix) { 1328*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject) Q, prefix)); 1329*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceSetFromOptions(Q)); 1330*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject) Q, NULL)); 1331066ea43fSLisandro Dalcin } 1332*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceSetUp(Q)); 1333066ea43fSLisandro Dalcin /* Create quadrature */ 1334066ea43fSLisandro Dalcin if (isSimplex) { 1335*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDTStroudConicalQuadrature(dim, 1, k+1, -1, +1, &q)); 1336*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDTStroudConicalQuadrature(dim-1, 1, k+1, -1, +1, &fq)); 1337066ea43fSLisandro Dalcin } else { 1338*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDTGaussTensorQuadrature(dim, 1, k+1, -1, +1, &q)); 1339*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDTGaussTensorQuadrature(dim-1, 1, k+1, -1, +1, &fq)); 1340066ea43fSLisandro Dalcin } 1341066ea43fSLisandro Dalcin /* Create finite element */ 1342*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFECreate(comm, fem)); 1343*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFESetType(*fem, PETSCFEBASIC)); 1344*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFESetNumComponents(*fem, Nc)); 1345*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFESetBasisSpace(*fem, P)); 1346*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFESetDualSpace(*fem, Q)); 1347*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFESetQuadrature(*fem, q)); 1348*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFESetFaceQuadrature(*fem, fq)); 1349066ea43fSLisandro Dalcin if (prefix) { 1350*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject) *fem, prefix)); 1351*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFESetFromOptions(*fem)); 1352*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject) *fem, NULL)); 1353066ea43fSLisandro Dalcin } 1354*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFESetUp(*fem)); 1355066ea43fSLisandro Dalcin /* Cleanup */ 1356*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSpaceDestroy(&P)); 1357*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceDestroy(&Q)); 1358*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscQuadratureDestroy(&q)); 1359*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscQuadratureDestroy(&fq)); 1360066ea43fSLisandro Dalcin /* Set finite element name */ 1361*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSNPrintf(name, sizeof(name), "%s%D", isSimplex? "P" : "Q", k)); 1362*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFESetName(*fem, name)); 1363066ea43fSLisandro Dalcin PetscFunctionReturn(0); 136496ca5757SLisandro Dalcin } 136596ca5757SLisandro Dalcin 1366d6689ca9SLisandro Dalcin /*@C 1367d6689ca9SLisandro Dalcin DMPlexCreateGmshFromFile - Create a DMPlex mesh from a Gmsh file 1368d6689ca9SLisandro Dalcin 1369d6689ca9SLisandro Dalcin + comm - The MPI communicator 1370d6689ca9SLisandro Dalcin . filename - Name of the Gmsh file 1371d6689ca9SLisandro Dalcin - interpolate - Create faces and edges in the mesh 1372d6689ca9SLisandro Dalcin 1373d6689ca9SLisandro Dalcin Output Parameter: 1374d6689ca9SLisandro Dalcin . dm - The DM object representing the mesh 1375d6689ca9SLisandro Dalcin 1376d6689ca9SLisandro Dalcin Level: beginner 1377d6689ca9SLisandro Dalcin 1378d6689ca9SLisandro Dalcin .seealso: DMPlexCreateFromFile(), DMPlexCreateGmsh(), DMPlexCreate() 1379d6689ca9SLisandro Dalcin @*/ 1380d6689ca9SLisandro Dalcin PetscErrorCode DMPlexCreateGmshFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) 1381d6689ca9SLisandro Dalcin { 1382d6689ca9SLisandro Dalcin PetscViewer viewer; 1383d6689ca9SLisandro Dalcin PetscMPIInt rank; 1384d6689ca9SLisandro Dalcin int fileType; 1385d6689ca9SLisandro Dalcin PetscViewerType vtype; 1386d6689ca9SLisandro Dalcin 1387d6689ca9SLisandro Dalcin PetscFunctionBegin; 1388*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 1389d6689ca9SLisandro Dalcin 1390d6689ca9SLisandro Dalcin /* Determine Gmsh file type (ASCII or binary) from file header */ 1391dd400576SPatrick Sanan if (rank == 0) { 13920598e1a2SLisandro Dalcin GmshFile gmsh[1]; 1393d6689ca9SLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 1394d6689ca9SLisandro Dalcin int snum; 1395d6689ca9SLisandro Dalcin float version; 1396d6689ca9SLisandro Dalcin 1397*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(gmsh,1)); 1398*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerCreate(PETSC_COMM_SELF, &gmsh->viewer)); 1399*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerSetType(gmsh->viewer, PETSCVIEWERASCII)); 1400*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFileSetMode(gmsh->viewer, FILE_MODE_READ)); 1401*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFileSetName(gmsh->viewer, filename)); 1402d6689ca9SLisandro Dalcin /* Read only the first two lines of the Gmsh file */ 1403*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadSection(gmsh, line)); 1404*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshExpect(gmsh, "$MeshFormat", line)); 1405*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadString(gmsh, line, 2)); 1406d6689ca9SLisandro Dalcin snum = sscanf(line, "%f %d", &version, &fileType); 14072c71b3e2SJacob Faibussowitsch PetscCheckFalse(snum != 2,PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line); 14082c71b3e2SJacob Faibussowitsch PetscCheckFalse(version < 2.2,PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at least 2.2", (double)version); 14092c71b3e2SJacob Faibussowitsch PetscCheckFalse((int)version == 3,PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f not supported", (double)version); 14102c71b3e2SJacob Faibussowitsch PetscCheckFalse(version > 4.1,PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at most 4.1", (double)version); 1411*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerDestroy(&gmsh->viewer)); 1412d6689ca9SLisandro Dalcin } 1413*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Bcast(&fileType, 1, MPI_INT, 0, comm)); 1414d6689ca9SLisandro Dalcin vtype = (fileType == 0) ? PETSCVIEWERASCII : PETSCVIEWERBINARY; 1415d6689ca9SLisandro Dalcin 1416d6689ca9SLisandro Dalcin /* Create appropriate viewer and build plex */ 1417*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerCreate(comm, &viewer)); 1418*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerSetType(viewer, vtype)); 1419*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 1420*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFileSetName(viewer, filename)); 1421*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateGmsh(comm, viewer, interpolate, dm)); 1422*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerDestroy(&viewer)); 1423d6689ca9SLisandro Dalcin PetscFunctionReturn(0); 1424d6689ca9SLisandro Dalcin } 1425d6689ca9SLisandro Dalcin 1426331830f3SMatthew G. Knepley /*@ 14277d282ae0SMichael Lange DMPlexCreateGmsh - Create a DMPlex mesh from a Gmsh file viewer 1428331830f3SMatthew G. Knepley 1429d083f849SBarry Smith Collective 1430331830f3SMatthew G. Knepley 1431331830f3SMatthew G. Knepley Input Parameters: 1432331830f3SMatthew G. Knepley + comm - The MPI communicator 1433331830f3SMatthew G. Knepley . viewer - The Viewer associated with a Gmsh file 1434331830f3SMatthew G. Knepley - interpolate - Create faces and edges in the mesh 1435331830f3SMatthew G. Knepley 1436331830f3SMatthew G. Knepley Output Parameter: 1437331830f3SMatthew G. Knepley . dm - The DM object representing the mesh 1438331830f3SMatthew G. Knepley 1439698a79b9SLisandro Dalcin Note: http://gmsh.info/doc/texinfo/gmsh.html#MSH-file-format 1440331830f3SMatthew G. Knepley 1441331830f3SMatthew G. Knepley Level: beginner 1442331830f3SMatthew G. Knepley 1443331830f3SMatthew G. Knepley .seealso: DMPLEX, DMCreate() 1444331830f3SMatthew G. Knepley @*/ 1445331830f3SMatthew G. Knepley PetscErrorCode DMPlexCreateGmsh(MPI_Comm comm, PetscViewer viewer, PetscBool interpolate, DM *dm) 1446331830f3SMatthew G. Knepley { 14470598e1a2SLisandro Dalcin GmshMesh *mesh = NULL; 144811c56cb0SLisandro Dalcin PetscViewer parentviewer = NULL; 14490598e1a2SLisandro Dalcin PetscBT periodicVerts = NULL; 14500598e1a2SLisandro Dalcin PetscBT periodicCells = NULL; 1451066ea43fSLisandro Dalcin DM cdm; 1452331830f3SMatthew G. Knepley PetscSection coordSection; 1453331830f3SMatthew G. Knepley Vec coordinates; 1454a45dabc8SMatthew G. Knepley DMLabel cellSets = NULL, faceSets = NULL, vertSets = NULL, marker = NULL, *regionSets; 1455066ea43fSLisandro Dalcin PetscInt dim = 0, coordDim = -1, order = 0; 14560598e1a2SLisandro Dalcin PetscInt numNodes = 0, numElems = 0, numVerts = 0, numCells = 0; 1457066ea43fSLisandro Dalcin PetscInt cell, cone[8], e, n, v, d; 145881a1af93SMatthew G. Knepley PetscBool binary, usemarker = PETSC_FALSE, useregions = PETSC_FALSE, markvertices = PETSC_FALSE; 14590598e1a2SLisandro Dalcin PetscBool hybrid = interpolate, periodic = PETSC_TRUE; 1460066ea43fSLisandro Dalcin PetscBool highOrder = PETSC_TRUE, highOrderSet, project = PETSC_FALSE; 1461066ea43fSLisandro Dalcin PetscBool isSimplex = PETSC_FALSE, isHybrid = PETSC_FALSE, hasTetra = PETSC_FALSE; 14620598e1a2SLisandro Dalcin PetscMPIInt rank; 1463331830f3SMatthew G. Knepley PetscErrorCode ierr; 1464331830f3SMatthew G. Knepley 1465331830f3SMatthew G. Knepley PetscFunctionBegin; 1466*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 1467ef12879bSLisandro Dalcin ierr = PetscObjectOptionsBegin((PetscObject)viewer);CHKERRQ(ierr); 1468*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsHead(PetscOptionsObject,"DMPlex Gmsh options")); 1469*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_gmsh_hybrid", "Generate hybrid cell bounds", "DMPlexCreateGmsh", hybrid, &hybrid, NULL)); 1470*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_gmsh_periodic","Read Gmsh periodic section", "DMPlexCreateGmsh", periodic, &periodic, NULL)); 1471*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_gmsh_highorder","Generate high-order coordinates", "DMPlexCreateGmsh", highOrder, &highOrder, &highOrderSet)); 1472*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_gmsh_project", "Project high-order coordinates to a different space", "DMPlexCreateGmsh", project, &project, NULL)); 1473*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_gmsh_use_marker", "Generate marker label", "DMPlexCreateGmsh", usemarker, &usemarker, NULL)); 1474*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_gmsh_use_regions", "Generate labels with region names", "DMPlexCreateGmsh", useregions, &useregions, NULL)); 1475*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-dm_plex_gmsh_mark_vertices", "Add vertices to generated labels", "DMPlexCreateGmsh", markvertices, &markvertices, NULL)); 1476*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBoundedInt("-dm_plex_gmsh_spacedim", "Embedding space dimension", "DMPlexCreateGmsh", coordDim, &coordDim, NULL, PETSC_DECIDE)); 1477*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsTail()); 1478ef12879bSLisandro Dalcin ierr = PetscOptionsEnd();CHKERRQ(ierr); 14790598e1a2SLisandro Dalcin 1480*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshCellInfoSetUp()); 148111c56cb0SLisandro Dalcin 1482*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm, dm)); 1483*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(*dm, DMPLEX)); 1484*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_CreateGmsh,*dm,NULL,NULL,NULL)); 148511c56cb0SLisandro Dalcin 1486*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &binary)); 148711c56cb0SLisandro Dalcin 148811c56cb0SLisandro Dalcin /* Binary viewers read on all ranks, get subviewer to read only in rank 0 */ 14893b46f529SLisandro Dalcin if (binary) { 149011c56cb0SLisandro Dalcin parentviewer = viewer; 1491*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerGetSubViewer(parentviewer, PETSC_COMM_SELF, &viewer)); 149211c56cb0SLisandro Dalcin } 149311c56cb0SLisandro Dalcin 1494dd400576SPatrick Sanan if (rank == 0) { 14950598e1a2SLisandro Dalcin GmshFile gmsh[1]; 1496698a79b9SLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 1497698a79b9SLisandro Dalcin PetscBool match; 1498331830f3SMatthew G. Knepley 1499*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArrayzero(gmsh,1)); 1500698a79b9SLisandro Dalcin gmsh->viewer = viewer; 1501698a79b9SLisandro Dalcin gmsh->binary = binary; 1502698a79b9SLisandro Dalcin 1503*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshMeshCreate(&mesh)); 15040598e1a2SLisandro Dalcin 1505698a79b9SLisandro Dalcin /* Read mesh format */ 1506*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadSection(gmsh, line)); 1507*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshExpect(gmsh, "$MeshFormat", line)); 1508*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadMeshFormat(gmsh)); 1509*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadEndSection(gmsh, "$EndMeshFormat", line)); 151011c56cb0SLisandro Dalcin 1511dc0ede3bSMatthew G. Knepley /* OPTIONAL Read physical names */ 1512*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadSection(gmsh, line)); 1513*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshMatch(gmsh, "$PhysicalNames", line, &match)); 1514dc0ede3bSMatthew G. Knepley if (match) { 1515*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshExpect(gmsh, "$PhysicalNames", line)); 1516*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadPhysicalNames(gmsh, mesh)); 1517*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadEndSection(gmsh, "$EndPhysicalNames", line)); 1518698a79b9SLisandro Dalcin /* Initial read for entity section */ 1519*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadSection(gmsh, line)); 1520dc0ede3bSMatthew G. Knepley } 152111c56cb0SLisandro Dalcin 1522de78e4feSLisandro Dalcin /* Read entities */ 1523698a79b9SLisandro Dalcin if (gmsh->fileFormat >= 40) { 1524*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshExpect(gmsh, "$Entities", line)); 1525*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadEntities(gmsh, mesh)); 1526*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadEndSection(gmsh, "$EndEntities", line)); 1527698a79b9SLisandro Dalcin /* Initial read for nodes section */ 1528*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadSection(gmsh, line)); 1529de78e4feSLisandro Dalcin } 1530de78e4feSLisandro Dalcin 1531698a79b9SLisandro Dalcin /* Read nodes */ 1532*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshExpect(gmsh, "$Nodes", line)); 1533*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadNodes(gmsh, mesh)); 1534*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadEndSection(gmsh, "$EndNodes", line)); 153511c56cb0SLisandro Dalcin 1536698a79b9SLisandro Dalcin /* Read elements */ 1537*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadSection(gmsh, line)); 1538*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshExpect(gmsh, "$Elements", line)); 1539*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadElements(gmsh, mesh)); 1540*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadEndSection(gmsh, "$EndElements", line)); 1541de78e4feSLisandro Dalcin 15420598e1a2SLisandro Dalcin /* Read periodic section (OPTIONAL) */ 1543698a79b9SLisandro Dalcin if (periodic) { 1544*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadSection(gmsh, line)); 1545*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshMatch(gmsh, "$Periodic", line, &periodic)); 1546ef12879bSLisandro Dalcin } 1547ef12879bSLisandro Dalcin if (periodic) { 1548*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshExpect(gmsh, "$Periodic", line)); 1549*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadPeriodic(gmsh, mesh)); 1550*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshReadEndSection(gmsh, "$EndPeriodic", line)); 1551698a79b9SLisandro Dalcin } 1552698a79b9SLisandro Dalcin 1553*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(gmsh->wbuf)); 1554*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(gmsh->sbuf)); 1555*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(gmsh->nbuf)); 15560598e1a2SLisandro Dalcin 15570598e1a2SLisandro Dalcin dim = mesh->dim; 1558066ea43fSLisandro Dalcin order = mesh->order; 15590598e1a2SLisandro Dalcin numNodes = mesh->numNodes; 15600598e1a2SLisandro Dalcin numElems = mesh->numElems; 15610598e1a2SLisandro Dalcin numVerts = mesh->numVerts; 15620598e1a2SLisandro Dalcin numCells = mesh->numCells; 1563066ea43fSLisandro Dalcin 1564066ea43fSLisandro Dalcin { 1565066ea43fSLisandro Dalcin GmshElement *elemA = mesh->numCells > 0 ? mesh->elements : NULL; 1566066ea43fSLisandro Dalcin GmshElement *elemB = elemA ? elemA + mesh->numCells - 1 : NULL; 1567066ea43fSLisandro Dalcin int ptA = elemA ? GmshCellMap[elemA->cellType].polytope : -1; 1568066ea43fSLisandro Dalcin int ptB = elemB ? GmshCellMap[elemB->cellType].polytope : -1; 1569066ea43fSLisandro Dalcin isSimplex = (ptA == GMSH_QUA || ptA == GMSH_HEX) ? PETSC_FALSE : PETSC_TRUE; 1570066ea43fSLisandro Dalcin isHybrid = (ptA == ptB) ? PETSC_FALSE : PETSC_TRUE; 1571066ea43fSLisandro Dalcin hasTetra = (ptA == GMSH_TET) ? PETSC_TRUE : PETSC_FALSE; 1572066ea43fSLisandro Dalcin } 1573698a79b9SLisandro Dalcin } 1574698a79b9SLisandro Dalcin 1575698a79b9SLisandro Dalcin if (parentviewer) { 1576*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRestoreSubViewer(parentviewer, PETSC_COMM_SELF, &viewer)); 1577698a79b9SLisandro Dalcin } 1578698a79b9SLisandro Dalcin 1579066ea43fSLisandro Dalcin { 1580066ea43fSLisandro Dalcin int buf[6]; 1581698a79b9SLisandro Dalcin 1582066ea43fSLisandro Dalcin buf[0] = (int)dim; 1583066ea43fSLisandro Dalcin buf[1] = (int)order; 1584066ea43fSLisandro Dalcin buf[2] = periodic; 1585066ea43fSLisandro Dalcin buf[3] = isSimplex; 1586066ea43fSLisandro Dalcin buf[4] = isHybrid; 1587066ea43fSLisandro Dalcin buf[5] = hasTetra; 1588066ea43fSLisandro Dalcin 1589*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Bcast(buf, 6, MPI_INT, 0, comm)); 1590066ea43fSLisandro Dalcin 1591066ea43fSLisandro Dalcin dim = buf[0]; 1592066ea43fSLisandro Dalcin order = buf[1]; 1593066ea43fSLisandro Dalcin periodic = buf[2] ? PETSC_TRUE : PETSC_FALSE; 1594066ea43fSLisandro Dalcin isSimplex = buf[3] ? PETSC_TRUE : PETSC_FALSE; 1595066ea43fSLisandro Dalcin isHybrid = buf[4] ? PETSC_TRUE : PETSC_FALSE; 1596066ea43fSLisandro Dalcin hasTetra = buf[5] ? PETSC_TRUE : PETSC_FALSE; 1597dea2a3c7SStefano Zampini } 1598dea2a3c7SStefano Zampini 1599066ea43fSLisandro Dalcin if (!highOrderSet) highOrder = (order > 1) ? PETSC_TRUE : PETSC_FALSE; 16002c71b3e2SJacob Faibussowitsch PetscCheckFalse(highOrder && isHybrid,comm, PETSC_ERR_SUP, "No support for discretization on hybrid meshes yet"); 1601066ea43fSLisandro Dalcin 16020598e1a2SLisandro Dalcin /* We do not want this label automatically computed, instead we fill it here */ 1603*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLabel(*dm, "celltype")); 160411c56cb0SLisandro Dalcin 1605a4bb7517SMichael Lange /* Allocate the cell-vertex mesh */ 1606*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetChart(*dm, 0, numCells+numVerts)); 16070598e1a2SLisandro Dalcin for (cell = 0; cell < numCells; ++cell) { 16080598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + cell; 16090598e1a2SLisandro Dalcin DMPolytopeType ctype = DMPolytopeTypeFromGmsh(elem->cellType); 16100598e1a2SLisandro Dalcin if (hybrid && hasTetra && ctype == DM_POLYTOPE_TRI_PRISM) ctype = DM_POLYTOPE_TRI_PRISM_TENSOR; 1611*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetConeSize(*dm, cell, elem->numVerts)); 1612*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCellType(*dm, cell, ctype)); 1613db397164SMichael Lange } 16140598e1a2SLisandro Dalcin for (v = numCells; v < numCells+numVerts; ++v) { 1615*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCellType(*dm, v, DM_POLYTOPE_POINT)); 161696ca5757SLisandro Dalcin } 1617*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetUp(*dm)); 161896ca5757SLisandro Dalcin 1619a4bb7517SMichael Lange /* Add cell-vertex connections */ 16200598e1a2SLisandro Dalcin for (cell = 0; cell < numCells; ++cell) { 16210598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + cell; 16220598e1a2SLisandro Dalcin for (v = 0; v < elem->numVerts; ++v) { 16230598e1a2SLisandro Dalcin const PetscInt nn = elem->nodes[v]; 16240598e1a2SLisandro Dalcin const PetscInt vv = mesh->vertexMap[nn]; 16250598e1a2SLisandro Dalcin cone[v] = numCells + vv; 1626db397164SMichael Lange } 1627*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReorderCell(*dm, cell, cone)); 1628*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetCone(*dm, cell, cone)); 1629a4bb7517SMichael Lange } 163096ca5757SLisandro Dalcin 1631*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(*dm, dim)); 1632*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSymmetrize(*dm)); 1633*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexStratify(*dm)); 1634331830f3SMatthew G. Knepley if (interpolate) { 16355fd9971aSMatthew G. Knepley DM idm; 1636331830f3SMatthew G. Knepley 1637*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexInterpolate(*dm, &idm)); 1638*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(dm)); 1639331830f3SMatthew G. Knepley *dm = idm; 1640331830f3SMatthew G. Knepley } 1641917266a4SLisandro Dalcin 164281a1af93SMatthew G. Knepley /* Create the label "marker" over the whole boundary */ 16432c71b3e2SJacob Faibussowitsch PetscCheckFalse(usemarker && !interpolate && dim > 1,comm,PETSC_ERR_SUP,"Cannot create marker label without interpolation"); 1644dd400576SPatrick Sanan if (rank == 0 && usemarker) { 1645d3f73514SStefano Zampini PetscInt f, fStart, fEnd; 1646d3f73514SStefano Zampini 1647*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLabel(*dm, "marker")); 1648*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(*dm, 1, &fStart, &fEnd)); 1649d3f73514SStefano Zampini for (f = fStart; f < fEnd; ++f) { 1650d3f73514SStefano Zampini PetscInt suppSize; 1651d3f73514SStefano Zampini 1652*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupportSize(*dm, f, &suppSize)); 1653d3f73514SStefano Zampini if (suppSize == 1) { 1654d3f73514SStefano Zampini PetscInt *cone = NULL, coneSize, p; 1655d3f73514SStefano Zampini 1656*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(*dm, f, PETSC_TRUE, &coneSize, &cone)); 1657d3f73514SStefano Zampini for (p = 0; p < coneSize; p += 2) { 1658*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelValue_Fast(*dm, &marker, "marker", cone[p], 1)); 1659d3f73514SStefano Zampini } 1660*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(*dm, f, PETSC_TRUE, &coneSize, &cone)); 1661d3f73514SStefano Zampini } 1662d3f73514SStefano Zampini } 1663d3f73514SStefano Zampini } 166416ad7e67SMichael Lange 1665dd400576SPatrick Sanan if (rank == 0) { 1666a45dabc8SMatthew G. Knepley const PetscInt Nr = useregions ? mesh->numRegions : 0; 166711c56cb0SLisandro Dalcin PetscInt vStart, vEnd; 1668d1a54cefSMatthew G. Knepley 1669*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(Nr, ®ionSets)); 1670*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(*dm, 0, &vStart, &vEnd)); 16710598e1a2SLisandro Dalcin for (cell = 0, e = 0; e < numElems; ++e) { 16720598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + e; 16736e1dd89aSLawrence Mitchell 16746e1dd89aSLawrence Mitchell /* Create cell sets */ 16750598e1a2SLisandro Dalcin if (elem->dim == dim && dim > 0) { 16760598e1a2SLisandro Dalcin if (elem->numTags > 0) { 1677a45dabc8SMatthew G. Knepley const PetscInt tag = elem->tags[0]; 1678a45dabc8SMatthew G. Knepley PetscInt r; 1679a45dabc8SMatthew G. Knepley 1680*5f80ce2aSJacob Faibussowitsch if (!Nr) CHKERRQ(DMSetLabelValue_Fast(*dm, &cellSets, "Cell Sets", cell, tag)); 1681a45dabc8SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 1682*5f80ce2aSJacob Faibussowitsch if (mesh->regionTags[r] == tag) CHKERRQ(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], cell, tag)); 1683a45dabc8SMatthew G. Knepley } 16846e1dd89aSLawrence Mitchell } 1685917266a4SLisandro Dalcin cell++; 16866e1dd89aSLawrence Mitchell } 16870c070f12SSander Arens 16880598e1a2SLisandro Dalcin /* Create face sets */ 16890598e1a2SLisandro Dalcin if (interpolate && elem->dim == dim-1) { 16900598e1a2SLisandro Dalcin PetscInt joinSize; 16910598e1a2SLisandro Dalcin const PetscInt *join = NULL; 1692a45dabc8SMatthew G. Knepley const PetscInt tag = elem->tags[0]; 1693a45dabc8SMatthew G. Knepley PetscInt r; 1694a45dabc8SMatthew G. Knepley 16950598e1a2SLisandro Dalcin /* Find the relevant facet with vertex joins */ 16960598e1a2SLisandro Dalcin for (v = 0; v < elem->numVerts; ++v) { 16970598e1a2SLisandro Dalcin const PetscInt nn = elem->nodes[v]; 16980598e1a2SLisandro Dalcin const PetscInt vv = mesh->vertexMap[nn]; 16990598e1a2SLisandro Dalcin cone[v] = vStart + vv; 17000598e1a2SLisandro Dalcin } 1701*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetFullJoin(*dm, elem->numVerts, cone, &joinSize, &join)); 17022c71b3e2SJacob Faibussowitsch PetscCheckFalse(joinSize != 1,PETSC_COMM_SELF, PETSC_ERR_SUP, "Could not determine Plex facet for Gmsh element %D (Plex cell %D)", elem->id, e); 1703*5f80ce2aSJacob Faibussowitsch if (!Nr) CHKERRQ(DMSetLabelValue_Fast(*dm, &faceSets, "Face Sets", join[0], tag)); 1704a45dabc8SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 1705*5f80ce2aSJacob Faibussowitsch if (mesh->regionTags[r] == tag) CHKERRQ(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], join[0], tag)); 1706a45dabc8SMatthew G. Knepley } 1707*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreJoin(*dm, elem->numVerts, cone, &joinSize, &join)); 17080598e1a2SLisandro Dalcin } 17090598e1a2SLisandro Dalcin 17100c070f12SSander Arens /* Create vertex sets */ 17110598e1a2SLisandro Dalcin if (elem->dim == 0) { 17120598e1a2SLisandro Dalcin if (elem->numTags > 0) { 17130598e1a2SLisandro Dalcin const PetscInt nn = elem->nodes[0]; 17140598e1a2SLisandro Dalcin const PetscInt vv = mesh->vertexMap[nn]; 1715a45dabc8SMatthew G. Knepley const PetscInt tag = elem->tags[0]; 1716a45dabc8SMatthew G. Knepley PetscInt r; 1717a45dabc8SMatthew G. Knepley 1718*5f80ce2aSJacob Faibussowitsch if (!Nr) CHKERRQ(DMSetLabelValue_Fast(*dm, &vertSets, "Vertex Sets", vStart + vv, tag)); 171981a1af93SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 1720*5f80ce2aSJacob Faibussowitsch if (mesh->regionTags[r] == tag) CHKERRQ(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], vStart + vv, tag)); 172181a1af93SMatthew G. Knepley } 172281a1af93SMatthew G. Knepley } 172381a1af93SMatthew G. Knepley } 172481a1af93SMatthew G. Knepley } 172581a1af93SMatthew G. Knepley if (markvertices) { 172681a1af93SMatthew G. Knepley for (v = 0; v < numNodes; ++v) { 172781a1af93SMatthew G. Knepley const PetscInt vv = mesh->vertexMap[v]; 172881a1af93SMatthew G. Knepley const PetscInt tag = mesh->nodelist->tag[v]; 172981a1af93SMatthew G. Knepley PetscInt r; 173081a1af93SMatthew G. Knepley 173181a1af93SMatthew G. Knepley if (tag != -1) { 1732*5f80ce2aSJacob Faibussowitsch if (!Nr) CHKERRQ(DMSetLabelValue_Fast(*dm, &vertSets, "Vertex Sets", vStart + vv, tag)); 1733a45dabc8SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 1734*5f80ce2aSJacob Faibussowitsch if (mesh->regionTags[r] == tag) CHKERRQ(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], vStart + vv, tag)); 17350598e1a2SLisandro Dalcin } 17360598e1a2SLisandro Dalcin } 17370598e1a2SLisandro Dalcin } 17380598e1a2SLisandro Dalcin } 1739*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(regionSets)); 1740a45dabc8SMatthew G. Knepley } 17410598e1a2SLisandro Dalcin 17427dd454faSLisandro Dalcin { /* Create Cell/Face/Vertex Sets labels at all processes */ 17437dd454faSLisandro Dalcin enum {n = 4}; 17447dd454faSLisandro Dalcin PetscBool flag[n]; 17457dd454faSLisandro Dalcin 17467dd454faSLisandro Dalcin flag[0] = cellSets ? PETSC_TRUE : PETSC_FALSE; 17477dd454faSLisandro Dalcin flag[1] = faceSets ? PETSC_TRUE : PETSC_FALSE; 17487dd454faSLisandro Dalcin flag[2] = vertSets ? PETSC_TRUE : PETSC_FALSE; 17497dd454faSLisandro Dalcin flag[3] = marker ? PETSC_TRUE : PETSC_FALSE; 1750*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Bcast(flag, n, MPIU_BOOL, 0, comm)); 1751*5f80ce2aSJacob Faibussowitsch if (flag[0]) CHKERRQ(DMCreateLabel(*dm, "Cell Sets")); 1752*5f80ce2aSJacob Faibussowitsch if (flag[1]) CHKERRQ(DMCreateLabel(*dm, "Face Sets")); 1753*5f80ce2aSJacob Faibussowitsch if (flag[2]) CHKERRQ(DMCreateLabel(*dm, "Vertex Sets")); 1754*5f80ce2aSJacob Faibussowitsch if (flag[3]) CHKERRQ(DMCreateLabel(*dm, "marker")); 17557dd454faSLisandro Dalcin } 17567dd454faSLisandro Dalcin 17570598e1a2SLisandro Dalcin if (periodic) { 1758*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTCreate(numVerts, &periodicVerts)); 17590598e1a2SLisandro Dalcin for (n = 0; n < numNodes; ++n) { 17600598e1a2SLisandro Dalcin if (mesh->vertexMap[n] >= 0) { 17610598e1a2SLisandro Dalcin if (PetscUnlikely(mesh->periodMap[n] != n)) { 17620598e1a2SLisandro Dalcin PetscInt m = mesh->periodMap[n]; 1763*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTSet(periodicVerts, mesh->vertexMap[n])); 1764*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTSet(periodicVerts, mesh->vertexMap[m])); 17650598e1a2SLisandro Dalcin } 17660598e1a2SLisandro Dalcin } 17670598e1a2SLisandro Dalcin } 1768*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTCreate(numCells, &periodicCells)); 17690598e1a2SLisandro Dalcin for (cell = 0; cell < numCells; ++cell) { 17700598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + cell; 17710598e1a2SLisandro Dalcin for (v = 0; v < elem->numVerts; ++v) { 17720598e1a2SLisandro Dalcin PetscInt nn = elem->nodes[v]; 17730598e1a2SLisandro Dalcin PetscInt vv = mesh->vertexMap[nn]; 17740598e1a2SLisandro Dalcin if (PetscUnlikely(PetscBTLookup(periodicVerts, vv))) { 1775*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTSet(periodicCells, cell)); break; 17760c070f12SSander Arens } 17770c070f12SSander Arens } 17780c070f12SSander Arens } 177916ad7e67SMichael Lange } 178016ad7e67SMichael Lange 1781066ea43fSLisandro Dalcin /* Setup coordinate DM */ 17820598e1a2SLisandro Dalcin if (coordDim < 0) coordDim = dim; 1783*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinateDim(*dm, coordDim)); 1784*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDM(*dm, &cdm)); 1785066ea43fSLisandro Dalcin if (highOrder) { 1786066ea43fSLisandro Dalcin PetscFE fe; 1787066ea43fSLisandro Dalcin PetscBool continuity = periodic ? PETSC_FALSE : PETSC_TRUE; 1788066ea43fSLisandro Dalcin PetscDTNodeType nodeType = PETSCDTNODES_EQUISPACED; 1789066ea43fSLisandro Dalcin 1790066ea43fSLisandro Dalcin if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */ 1791066ea43fSLisandro Dalcin 1792*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshCreateFE(comm, NULL, isSimplex, continuity, nodeType, dim, coordDim, order, &fe)); 1793*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_fe_view")); 1794*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetField(cdm, 0, NULL, (PetscObject) fe)); 1795*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFEDestroy(&fe)); 1796*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateDS(cdm)); 1797066ea43fSLisandro Dalcin } 1798066ea43fSLisandro Dalcin 1799066ea43fSLisandro Dalcin /* Create coordinates */ 1800066ea43fSLisandro Dalcin if (highOrder) { 1801066ea43fSLisandro Dalcin 1802066ea43fSLisandro Dalcin PetscInt maxDof = GmshNumNodes_HEX(order)*coordDim; 1803066ea43fSLisandro Dalcin double *coords = mesh ? mesh->nodelist->xyz : NULL; 1804066ea43fSLisandro Dalcin PetscSection section; 1805066ea43fSLisandro Dalcin PetscScalar *cellCoords; 1806066ea43fSLisandro Dalcin 1807*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLocalSection(cdm, NULL)); 1808*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection(cdm, &coordSection)); 1809*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionClone(coordSection, §ion)); 1810*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetClosurePermutationTensor(cdm, 0, section)); /* XXX Implement DMPlexSetClosurePermutationLexicographic() */ 1811066ea43fSLisandro Dalcin 1812*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLocalVector(cdm, &coordinates)); 1813*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(maxDof, &cellCoords)); 1814066ea43fSLisandro Dalcin for (cell = 0; cell < numCells; ++cell) { 1815066ea43fSLisandro Dalcin GmshElement *elem = mesh->elements + cell; 1816066ea43fSLisandro Dalcin const int *lexorder = GmshCellMap[elem->cellType].lexorder(); 1817b9bf55e5SMatthew G. Knepley int s = 0; 1818066ea43fSLisandro Dalcin for (n = 0; n < elem->numNodes; ++n) { 1819b9bf55e5SMatthew G. Knepley while (lexorder[n+s] < 0) ++s; 1820b9bf55e5SMatthew G. Knepley const PetscInt node = elem->nodes[lexorder[n+s]]; 1821b9bf55e5SMatthew G. Knepley for (d = 0; d < coordDim; ++d) cellCoords[(n+s)*coordDim+d] = (PetscReal) coords[node*3+d]; 1822b9bf55e5SMatthew G. Knepley } 1823b9bf55e5SMatthew G. Knepley if (s) { 1824b9bf55e5SMatthew G. Knepley /* For the coordinate mapping we weight vertices by -1/4 and edges by 1/2, which we get from Q_2 interpolation */ 1825b9bf55e5SMatthew G. Knepley PetscReal quaCenterWeights[9] = {-0.25, 0.5, -0.25, 0.5, 0.0, 0.5, -0.25, 0.5, -0.25}; 1826b9bf55e5SMatthew G. Knepley /* For the coordinate mapping we weight vertices by -1/4 and edges by 1/2, which we get from Q_2 interpolation */ 1827b9bf55e5SMatthew G. Knepley PetscReal hexBottomWeights[27] = {-0.25, 0.5, -0.25, 0.5, 0.0, 0.5, -0.25, 0.5, -0.25, 1828b9bf55e5SMatthew G. Knepley 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1829b9bf55e5SMatthew G. Knepley 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; 1830b9bf55e5SMatthew G. Knepley PetscReal hexFrontWeights[27] = {-0.25, 0.5, -0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1831b9bf55e5SMatthew G. Knepley 0.5, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1832b9bf55e5SMatthew G. Knepley -0.25, 0.5, -0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; 1833b9bf55e5SMatthew G. Knepley PetscReal hexLeftWeights[27] = {-0.25, 0.0, 0.0, 0.5, 0.0, 0.0, -0.25, 0.0, 0.0, 1834b9bf55e5SMatthew G. Knepley 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 1835b9bf55e5SMatthew G. Knepley -0.25, 0.0, 0.0, 0.5, 0.0, 0.0, -0.25, 0.0, 0.0}; 1836b9bf55e5SMatthew G. Knepley PetscReal hexRightWeights[27] = { 0.0, 0.0, -0.25, 0.0, 0.0, 0.5, 0.0, 0.0, -0.25, 1837b9bf55e5SMatthew G. Knepley 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 1838b9bf55e5SMatthew G. Knepley 0.0, 0.0, -0.25, 0.0, 0.0, 0.5, 0.0, 0.0, -0.25}; 1839b9bf55e5SMatthew G. Knepley PetscReal hexBackWeights[27] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.25, 0.5, -0.25, 1840b9bf55e5SMatthew G. Knepley 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.5, 1841b9bf55e5SMatthew G. Knepley 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.25, 0.5, -0.25}; 1842b9bf55e5SMatthew G. Knepley PetscReal hexTopWeights[27] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1843b9bf55e5SMatthew G. Knepley 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1844b9bf55e5SMatthew G. Knepley -0.25, 0.5, -0.25, 0.5, 0.0, 0.5, -0.25, 0.5, -0.25}; 1845b9bf55e5SMatthew G. Knepley PetscReal hexCenterWeights[27] = {-0.25, 0.25, -0.25, 0.25, 0.0, 0.25, -0.25, 0.25, -0.25, 1846b9bf55e5SMatthew G. Knepley 0.25, 0.0, 0.25, 0.0, 0.0, 0.0, 0.25, 0.0, 0.25, 1847b9bf55e5SMatthew G. Knepley -0.25, 0.25, -0.25, 0.25, 0.0, 0.25, -0.25, 0.25, -0.25}; 1848b9bf55e5SMatthew G. Knepley PetscReal *sdWeights2[9] = {NULL, NULL, NULL, NULL, quaCenterWeights, NULL, NULL, NULL, NULL}; 1849b9bf55e5SMatthew G. Knepley PetscReal *sdWeights3[27] = {NULL, NULL, NULL, NULL, hexBottomWeights, NULL, NULL, NULL, NULL, 1850b9bf55e5SMatthew G. Knepley NULL, hexFrontWeights, NULL, hexLeftWeights, hexCenterWeights, hexRightWeights, NULL, hexBackWeights, NULL, 1851b9bf55e5SMatthew G. Knepley NULL, NULL, NULL, NULL, hexTopWeights, NULL, NULL, NULL, NULL}; 1852b9bf55e5SMatthew G. Knepley PetscReal **sdWeights[4] = {NULL, NULL, sdWeights2, sdWeights3}; 1853b9bf55e5SMatthew G. Knepley 1854b9bf55e5SMatthew G. Knepley /* Missing entries in serendipity cell, only works for 8-node quad and 20-node hex */ 1855b9bf55e5SMatthew G. Knepley for (n = 0; n < elem->numNodes+s; ++n) { 1856b9bf55e5SMatthew G. Knepley if (lexorder[n] >= 0) continue; 1857b9bf55e5SMatthew G. Knepley for (d = 0; d < coordDim; ++d) cellCoords[n*coordDim+d] = 0.0; 1858b9bf55e5SMatthew G. Knepley for (int bn = 0; bn < elem->numNodes+s; ++bn) { 1859b9bf55e5SMatthew G. Knepley if (lexorder[bn] < 0) continue; 1860b9bf55e5SMatthew G. Knepley const PetscReal *weights = sdWeights[coordDim][n]; 1861b9bf55e5SMatthew G. Knepley const PetscInt bnode = elem->nodes[lexorder[bn]]; 1862b9bf55e5SMatthew G. Knepley for (d = 0; d < coordDim; ++d) cellCoords[n*coordDim+d] += weights[bn] * (PetscReal) coords[bnode*3+d]; 1863b9bf55e5SMatthew G. Knepley } 1864b9bf55e5SMatthew G. Knepley } 1865066ea43fSLisandro Dalcin } 1866*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVecSetClosure(cdm, section, coordinates, cell, cellCoords, INSERT_VALUES)); 1867066ea43fSLisandro Dalcin } 1868*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(§ion)); 1869*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(cellCoords)); 1870066ea43fSLisandro Dalcin 1871066ea43fSLisandro Dalcin } else { 1872066ea43fSLisandro Dalcin 1873066ea43fSLisandro Dalcin PetscInt *nodeMap; 1874066ea43fSLisandro Dalcin double *coords = mesh ? mesh->nodelist->xyz : NULL; 1875066ea43fSLisandro Dalcin PetscScalar *pointCoords; 1876066ea43fSLisandro Dalcin 1877*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection(cdm, &coordSection)); 1878*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetNumFields(coordSection, 1)); 1879*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, coordDim)); 18800598e1a2SLisandro Dalcin if (periodic) { /* we need to localize coordinates on cells */ 1881*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(coordSection, 0, numCells+numVerts)); 1882f45c9589SStefano Zampini } else { 1883*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(coordSection, numCells, numCells+numVerts)); 1884f45c9589SStefano Zampini } 18850598e1a2SLisandro Dalcin if (periodic) { 18860598e1a2SLisandro Dalcin for (cell = 0; cell < numCells; ++cell) { 18870598e1a2SLisandro Dalcin if (PetscUnlikely(PetscBTLookup(periodicCells, cell))) { 18880598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + cell; 18890598e1a2SLisandro Dalcin PetscInt dof = elem->numVerts * coordDim; 1890*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(coordSection, cell, dof)); 1891*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldDof(coordSection, cell, 0, dof)); 1892f45c9589SStefano Zampini } 1893f45c9589SStefano Zampini } 1894f45c9589SStefano Zampini } 18950598e1a2SLisandro Dalcin for (v = numCells; v < numCells+numVerts; ++v) { 1896*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(coordSection, v, coordDim)); 1897*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, coordDim)); 18980598e1a2SLisandro Dalcin } 1899*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(coordSection)); 1900066ea43fSLisandro Dalcin 1901*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLocalVector(cdm, &coordinates)); 1902*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(coordinates, &pointCoords)); 19030598e1a2SLisandro Dalcin if (periodic) { 19040598e1a2SLisandro Dalcin for (cell = 0; cell < numCells; ++cell) { 19050598e1a2SLisandro Dalcin if (PetscUnlikely(PetscBTLookup(periodicCells, cell))) { 19060598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + cell; 19070598e1a2SLisandro Dalcin PetscInt off, node; 19080598e1a2SLisandro Dalcin for (v = 0; v < elem->numVerts; ++v) 19090598e1a2SLisandro Dalcin cone[v] = elem->nodes[v]; 1910*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexReorderCell(cdm, cell, cone)); 1911*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(coordSection, cell, &off)); 19120598e1a2SLisandro Dalcin for (v = 0; v < elem->numVerts; ++v) 19130598e1a2SLisandro Dalcin for (node = cone[v], d = 0; d < coordDim; ++d) 1914066ea43fSLisandro Dalcin pointCoords[off++] = (PetscReal) coords[node*3+d]; 1915331830f3SMatthew G. Knepley } 1916331830f3SMatthew G. Knepley } 1917331830f3SMatthew G. Knepley } 1918*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numVerts, &nodeMap)); 19190598e1a2SLisandro Dalcin for (n = 0; n < numNodes; n++) 19200598e1a2SLisandro Dalcin if (mesh->vertexMap[n] >= 0) 1921066ea43fSLisandro Dalcin nodeMap[mesh->vertexMap[n]] = n; 19220598e1a2SLisandro Dalcin for (v = 0; v < numVerts; ++v) { 1923066ea43fSLisandro Dalcin PetscInt off, node = nodeMap[v]; 1924*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(coordSection, numCells + v, &off)); 19250598e1a2SLisandro Dalcin for (d = 0; d < coordDim; ++d) 1926066ea43fSLisandro Dalcin pointCoords[off+d] = (PetscReal) coords[node*3+d]; 19270598e1a2SLisandro Dalcin } 1928*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(nodeMap)); 1929*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(coordinates, &pointCoords)); 1930066ea43fSLisandro Dalcin 1931066ea43fSLisandro Dalcin } 1932066ea43fSLisandro Dalcin 1933*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates")); 1934*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetBlockSize(coordinates, coordDim)); 1935*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinatesLocal(*dm, coordinates)); 1936*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&coordinates)); 1937*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetPeriodicity(*dm, periodic, NULL, NULL, NULL)); 193811c56cb0SLisandro Dalcin 1939*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshMeshDestroy(&mesh)); 1940*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTDestroy(&periodicVerts)); 1941*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTDestroy(&periodicCells)); 194211c56cb0SLisandro Dalcin 1943066ea43fSLisandro Dalcin if (highOrder && project) { 1944066ea43fSLisandro Dalcin PetscFE fe; 1945066ea43fSLisandro Dalcin const char prefix[] = "dm_plex_gmsh_project_"; 1946066ea43fSLisandro Dalcin PetscBool continuity = periodic ? PETSC_FALSE : PETSC_TRUE; 1947066ea43fSLisandro Dalcin PetscDTNodeType nodeType = PETSCDTNODES_GAUSSJACOBI; 1948066ea43fSLisandro Dalcin 1949066ea43fSLisandro Dalcin if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */ 1950066ea43fSLisandro Dalcin 1951*5f80ce2aSJacob Faibussowitsch CHKERRQ(GmshCreateFE(comm, prefix, isSimplex, continuity, nodeType, dim, coordDim, order, &fe)); 1952*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_project_fe_view")); 1953*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMProjectCoordinates(*dm, fe)); 1954*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFEDestroy(&fe)); 1955066ea43fSLisandro Dalcin } 1956066ea43fSLisandro Dalcin 1957*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_CreateGmsh,*dm,NULL,NULL,NULL)); 1958331830f3SMatthew G. Knepley PetscFunctionReturn(0); 1959331830f3SMatthew G. Knepley } 1960