Nektar++
Public Member Functions | Static Public Member Functions | Static Public Attributes | Private Member Functions | Static Private Member Functions | Private Attributes | List of all members
Nektar::Utilities::InputGmsh Class Reference

#include <InputGmsh.h>

Inheritance diagram for Nektar::Utilities::InputGmsh:
[legend]

Public Member Functions

 InputGmsh (NekMeshUtils::MeshSharedPtr m)
 Set up InputGmsh object. More...
 
virtual ~InputGmsh ()
 
virtual void Process ()
 
- Public Member Functions inherited from Nektar::NekMeshUtils::InputModule
NEKMESHUTILS_EXPORT InputModule (MeshSharedPtr p_m)
 
NEKMESHUTILS_EXPORT void OpenStream ()
 Open a file for input. More...
 
- Public Member Functions inherited from Nektar::NekMeshUtils::Module
NEKMESHUTILS_EXPORT Module (MeshSharedPtr p_m)
 
NEKMESHUTILS_EXPORT void RegisterConfig (std::string key, std::string value=std::string())
 Register a configuration option with a module. More...
 
NEKMESHUTILS_EXPORT void PrintConfig ()
 Print out all configuration options for a module. More...
 
NEKMESHUTILS_EXPORT void SetDefaults ()
 Sets default configuration options for those which have not been set. More...
 
NEKMESHUTILS_EXPORT MeshSharedPtr GetMesh ()
 
virtual NEKMESHUTILS_EXPORT void ProcessVertices ()
 Extract element vertices. More...
 
virtual NEKMESHUTILS_EXPORT void ProcessEdges (bool ReprocessEdges=true)
 Extract element edges. More...
 
virtual NEKMESHUTILS_EXPORT void ProcessFaces (bool ReprocessFaces=true)
 Extract element faces. More...
 
virtual NEKMESHUTILS_EXPORT void ProcessElements ()
 Generate element IDs. More...
 
virtual NEKMESHUTILS_EXPORT void ProcessComposites ()
 Generate composites. More...
 
virtual NEKMESHUTILS_EXPORT void ClearElementLinks ()
 

Static Public Member Functions

static NekMeshUtils::ModuleSharedPtr create (NekMeshUtils::MeshSharedPtr m)
 Creates an instance of this class. More...
 
static std::map< unsigned int, NekMeshUtils::ElmtConfigGenElmMap ()
 
static std::vector< int > CreateReordering (unsigned int InputGmshEntity)
 Create a reordering map for a given element. More...
 

Static Public Attributes

static NekMeshUtils::ModuleKey className
 ModuleKey for class. More...
 
static std::map< unsigned int, NekMeshUtils::ElmtConfigelmMap = InputGmsh::GenElmMap()
 

Private Member Functions

int GetNnodes (unsigned int InputGmshEntity)
 
void ReadNextNode ()
 
void ReadNextNodeBlock (int nVertices=0)
 
void SaveNode (int id, NekDouble x=0, NekDouble y=0, NekDouble z=0)
 
void ReadNextElement (int tag=0, int elm_type=0)
 

Static Private Member Functions

static std::vector< int > TriReordering (NekMeshUtils::ElmtConfig conf)
 Create a reordering for triangles. More...
 
static std::vector< int > QuadReordering (NekMeshUtils::ElmtConfig conf)
 Create a reordering for quadrilaterals. More...
 
static std::vector< int > HexReordering (NekMeshUtils::ElmtConfig conf)
 Create a reordering for hexahedra. More...
 
static std::vector< int > PrismReordering (NekMeshUtils::ElmtConfig conf)
 Create a reordering for prisms. More...
 
static std::vector< int > TetReordering (NekMeshUtils::ElmtConfig conf)
 Create a reordering for tetrahedra. More...
 
static std::vector< int > LineReordering (NekMeshUtils::ElmtConfig conf)
 

Private Attributes

NekDouble m_version
 
int m_prevId
 
std::map< int, int > m_idMap
 
int m_maxTagId
 
std::unordered_map< int, std::vector< int > > m_orderingMap
 

Additional Inherited Members

- Protected Member Functions inherited from Nektar::NekMeshUtils::InputModule
NEKMESHUTILS_EXPORT void PrintSummary ()
 Print summary of elements. More...
 
- Protected Member Functions inherited from Nektar::NekMeshUtils::Module
NEKMESHUTILS_EXPORT void ReorderPrisms (PerMap &perFaces)
 Reorder node IDs so that prisms and tetrahedra are aligned correctly. More...
 
NEKMESHUTILS_EXPORT void PrismLines (int prism, PerMap &perFaces, std::set< int > &prismsDone, std::vector< ElementSharedPtr > &line)
 
- Protected Attributes inherited from Nektar::NekMeshUtils::InputModule
io::filtering_istream m_mshFile
 Input stream. More...
 
std::ifstream m_mshFileStream
 Input stream. More...
 
- Protected Attributes inherited from Nektar::NekMeshUtils::Module
MeshSharedPtr m_mesh
 Mesh object. More...
 
std::map< std::string, ConfigOptionm_config
 List of configuration values. More...
 

Detailed Description

Converter for Gmsh files.

Definition at line 48 of file InputGmsh.h.

Constructor & Destructor Documentation

◆ InputGmsh()

Nektar::Utilities::InputGmsh::InputGmsh ( NekMeshUtils::MeshSharedPtr  m)

Set up InputGmsh object.

Definition at line 700 of file InputGmsh.cpp.

701  : InputModule(m), m_version(0.0), m_prevId(-1), m_maxTagId(-1)
702 {
703 }
NEKMESHUTILS_EXPORT InputModule(MeshSharedPtr p_m)

◆ ~InputGmsh()

Nektar::Utilities::InputGmsh::~InputGmsh ( )
virtual

Definition at line 705 of file InputGmsh.cpp.

706 {
707 }

Member Function Documentation

◆ create()

static NekMeshUtils::ModuleSharedPtr Nektar::Utilities::InputGmsh::create ( NekMeshUtils::MeshSharedPtr  m)
inlinestatic

Creates an instance of this class.

Definition at line 56 of file InputGmsh.h.

References Nektar::MemoryManager< DataType >::AllocateSharedPtr().

57  {
59  }
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.

◆ CreateReordering()

vector< int > Nektar::Utilities::InputGmsh::CreateReordering ( unsigned int  InputGmshEntity)
static

Create a reordering map for a given element.

Since Gmsh and Nektar++ have different vertex, edge and face orientations, we need to reorder the nodes in a Gmsh MSH file so that they work with the Nektar++ orderings, since this is what is used in the elements defined in the converter.

Definition at line 1218 of file InputGmsh.cpp.

References Nektar::LibUtilities::eHexahedron, elmMap, Nektar::LibUtilities::ePrism, Nektar::LibUtilities::eQuadrilateral, Nektar::LibUtilities::eSegment, Nektar::LibUtilities::eTetrahedron, Nektar::LibUtilities::eTriangle, HexReordering(), LineReordering(), PrismReordering(), QuadReordering(), TetReordering(), and TriReordering().

Referenced by Nektar::Utilities::OutputGmsh::Process(), and ReadNextElement().

1219 {
1220  auto it = elmMap.find(InputGmshEntity);
1221 
1222  if (it == elmMap.end())
1223  {
1224  cerr << "Unknown element type " << InputGmshEntity << endl;
1225  abort();
1226  }
1227 
1228  // For specific elements, call the appropriate function to perform
1229  // the renumbering.
1230  switch (it->second.m_e)
1231  {
1233  return TriReordering(it->second);
1234  break;
1236  return QuadReordering(it->second);
1237  break;
1239  return TetReordering(it->second);
1240  break;
1241  case LibUtilities::ePrism:
1242  return PrismReordering(it->second);
1243  break;
1245  return HexReordering(it->second);
1246  break;
1248  return LineReordering(it->second);
1249  default:
1250  break;
1251  }
1252 
1253  // Default: no reordering.
1254  vector<int> returnVal;
1255  return returnVal;
1256 }
static std::vector< int > PrismReordering(NekMeshUtils::ElmtConfig conf)
Create a reordering for prisms.
Definition: InputGmsh.cpp:1523
static std::vector< int > TetReordering(NekMeshUtils::ElmtConfig conf)
Create a reordering for tetrahedra.
Definition: InputGmsh.cpp:1371
static std::vector< int > HexReordering(NekMeshUtils::ElmtConfig conf)
Create a reordering for hexahedra.
Definition: InputGmsh.cpp:1742
static std::vector< int > LineReordering(NekMeshUtils::ElmtConfig conf)
Definition: InputGmsh.cpp:1258
static std::vector< int > QuadReordering(NekMeshUtils::ElmtConfig conf)
Create a reordering for quadrilaterals.
Definition: InputGmsh.cpp:1323
static std::vector< int > TriReordering(NekMeshUtils::ElmtConfig conf)
Create a reordering for triangles.
Definition: InputGmsh.cpp:1274
static std::map< unsigned int, NekMeshUtils::ElmtConfig > elmMap
Definition: InputGmsh.h:67

◆ GenElmMap()

std::map< unsigned int, ElmtConfig > Nektar::Utilities::InputGmsh::GenElmMap ( )
static

Definition at line 1890 of file InputGmsh.cpp.

References Nektar::LibUtilities::eHexahedron, Nektar::ePoint, Nektar::LibUtilities::ePrism, Nektar::LibUtilities::ePyramid, Nektar::LibUtilities::eQuadrilateral, Nektar::LibUtilities::eSegment, Nektar::LibUtilities::eTetrahedron, and Nektar::LibUtilities::eTriangle.

Referenced by Nektar::Utilities::OutputGmsh::OutputGmsh().

1891 {
1892  using namespace LibUtilities;
1893  std::map<unsigned int, ElmtConfig> tmp;
1894 
1895  // Elmt type, order, face, volume
1896  tmp[ 1] = ElmtConfig(eSegment, 1, false, false);
1897  tmp[ 2] = ElmtConfig(eTriangle, 1, false, false);
1898  tmp[ 3] = ElmtConfig(eQuadrilateral, 1, false, false);
1899  tmp[ 4] = ElmtConfig(eTetrahedron, 1, false, false);
1900  tmp[ 5] = ElmtConfig(eHexahedron, 1, false, false);
1901  tmp[ 6] = ElmtConfig(ePrism, 1, false, false);
1902  tmp[ 7] = ElmtConfig(ePyramid, 1, false, false);
1903  tmp[ 8] = ElmtConfig(eSegment, 2, true, false);
1904  tmp[ 9] = ElmtConfig(eTriangle, 2, false, false);
1905  tmp[ 10] = ElmtConfig(eQuadrilateral, 2, true, false);
1906  tmp[ 11] = ElmtConfig(eTetrahedron, 2, false, false);
1907  tmp[ 12] = ElmtConfig(eHexahedron, 2, true, true);
1908  tmp[ 13] = ElmtConfig(ePrism, 2, true, false);
1909  tmp[ 14] = ElmtConfig(ePyramid, 2, true, false);
1910  tmp[ 15] = ElmtConfig(ePoint, 1, false, false);
1911  tmp[ 16] = ElmtConfig(eQuadrilateral, 2, false, false);
1912  tmp[ 17] = ElmtConfig(eHexahedron, 2, false, false);
1913  tmp[ 18] = ElmtConfig(ePrism, 2, false, false);
1914  tmp[ 19] = ElmtConfig(ePyramid, 2, false, false);
1915  tmp[ 20] = ElmtConfig(eTriangle, 3, false, false);
1916  tmp[ 21] = ElmtConfig(eTriangle, 3, true, false);
1917  tmp[ 22] = ElmtConfig(eTriangle, 4, false, false);
1918  tmp[ 23] = ElmtConfig(eTriangle, 4, true, false);
1919  tmp[ 24] = ElmtConfig(eTriangle, 5, false, false);
1920  tmp[ 25] = ElmtConfig(eTriangle, 5, true, false);
1921  tmp[ 26] = ElmtConfig(eSegment, 3, true, false);
1922  tmp[ 27] = ElmtConfig(eSegment, 4, true, false);
1923  tmp[ 28] = ElmtConfig(eSegment, 5, true, false);
1924  tmp[ 29] = ElmtConfig(eTetrahedron, 3, true, false);
1925  tmp[ 30] = ElmtConfig(eTetrahedron, 4, true, true);
1926  tmp[ 31] = ElmtConfig(eTetrahedron, 5, true, true);
1927  tmp[ 32] = ElmtConfig(eTetrahedron, 4, true, false);
1928  tmp[ 33] = ElmtConfig(eTetrahedron, 5, true, false);
1929  tmp[ 36] = ElmtConfig(eQuadrilateral, 3, true, false);
1930  tmp[ 37] = ElmtConfig(eQuadrilateral, 4, true, false);
1931  tmp[ 38] = ElmtConfig(eQuadrilateral, 5, true, false);
1932  tmp[ 39] = ElmtConfig(eQuadrilateral, 3, false, false);
1933  tmp[ 40] = ElmtConfig(eQuadrilateral, 4, false, false);
1934  tmp[ 41] = ElmtConfig(eQuadrilateral, 5, false, false);
1935  tmp[ 42] = ElmtConfig(eTriangle, 6, true, false);
1936  tmp[ 43] = ElmtConfig(eTriangle, 7, true, false);
1937  tmp[ 44] = ElmtConfig(eTriangle, 8, true, false);
1938  tmp[ 45] = ElmtConfig(eTriangle, 9, true, false);
1939  tmp[ 46] = ElmtConfig(eTriangle, 10, true, false);
1940  tmp[ 47] = ElmtConfig(eQuadrilateral, 6, true, false);
1941  tmp[ 48] = ElmtConfig(eQuadrilateral, 7, true, false);
1942  tmp[ 49] = ElmtConfig(eQuadrilateral, 8, true, false);
1943  tmp[ 50] = ElmtConfig(eQuadrilateral, 9, true, false);
1944  tmp[ 51] = ElmtConfig(eQuadrilateral, 10, true, false);
1945  tmp[ 52] = ElmtConfig(eTriangle, 6, false, false);
1946  tmp[ 53] = ElmtConfig(eTriangle, 7, false, false);
1947  tmp[ 54] = ElmtConfig(eTriangle, 8, false, false);
1948  tmp[ 55] = ElmtConfig(eTriangle, 9, false, false);
1949  tmp[ 56] = ElmtConfig(eTriangle, 10, false, false);
1950  tmp[ 57] = ElmtConfig(eQuadrilateral, 6, false, false);
1951  tmp[ 58] = ElmtConfig(eQuadrilateral, 7, false, false);
1952  tmp[ 59] = ElmtConfig(eQuadrilateral, 8, false, false);
1953  tmp[ 60] = ElmtConfig(eQuadrilateral, 9, false, false);
1954  tmp[ 61] = ElmtConfig(eQuadrilateral, 10, false, false);
1955  tmp[ 62] = ElmtConfig(eSegment, 6, true, false);
1956  tmp[ 63] = ElmtConfig(eSegment, 7, true, false);
1957  tmp[ 64] = ElmtConfig(eSegment, 8, true, false);
1958  tmp[ 65] = ElmtConfig(eSegment, 9, true, false);
1959  tmp[ 66] = ElmtConfig(eSegment, 10, true, false);
1960  tmp[ 71] = ElmtConfig(eTetrahedron, 6, true, true);
1961  tmp[ 72] = ElmtConfig(eTetrahedron, 7, true, true);
1962  tmp[ 73] = ElmtConfig(eTetrahedron, 8, true, true);
1963  tmp[ 74] = ElmtConfig(eTetrahedron, 9, true, true);
1964  tmp[ 75] = ElmtConfig(eTetrahedron, 10, true, true);
1965  tmp[ 79] = ElmtConfig(eTetrahedron, 6, true, false);
1966  tmp[ 80] = ElmtConfig(eTetrahedron, 7, true, false);
1967  tmp[ 81] = ElmtConfig(eTetrahedron, 8, true, false);
1968  tmp[ 82] = ElmtConfig(eTetrahedron, 9, true, false);
1969  tmp[ 83] = ElmtConfig(eTetrahedron, 10, true, false);
1970  tmp[ 90] = ElmtConfig(ePrism, 3, true, true);
1971  tmp[ 91] = ElmtConfig(ePrism, 4, true, true);
1972  tmp[ 92] = ElmtConfig(eHexahedron, 3, true, true);
1973  tmp[ 93] = ElmtConfig(eHexahedron, 4, true, true);
1974  tmp[ 94] = ElmtConfig(eHexahedron, 5, true, true);
1975  tmp[ 95] = ElmtConfig(eHexahedron, 6, true, true);
1976  tmp[ 96] = ElmtConfig(eHexahedron, 7, true, true);
1977  tmp[ 97] = ElmtConfig(eHexahedron, 8, true, true);
1978  tmp[ 98] = ElmtConfig(eHexahedron, 9, true, true);
1979  tmp[ 99] = ElmtConfig(eHexahedron, 3, true, false);
1980  tmp[100] = ElmtConfig(eHexahedron, 4, true, false);
1981  tmp[101] = ElmtConfig(eHexahedron, 5, true, false);
1982  tmp[102] = ElmtConfig(eHexahedron, 6, true, false);
1983  tmp[103] = ElmtConfig(eHexahedron, 7, true, false);
1984  tmp[104] = ElmtConfig(eHexahedron, 8, true, false);
1985  tmp[105] = ElmtConfig(eHexahedron, 9, true, false);
1986  tmp[106] = ElmtConfig(ePrism, 5, true, true);
1987  tmp[107] = ElmtConfig(ePrism, 6, true, true);
1988  tmp[108] = ElmtConfig(ePrism, 7, true, true);
1989  tmp[109] = ElmtConfig(ePrism, 8, true, true);
1990  tmp[110] = ElmtConfig(ePrism, 9, true, true);
1991  tmp[111] = ElmtConfig(ePrism, 3, true, false);
1992  tmp[112] = ElmtConfig(ePrism, 4, true, false);
1993  tmp[113] = ElmtConfig(ePrism, 5, true, false);
1994  tmp[114] = ElmtConfig(ePrism, 6, true, false);
1995  tmp[115] = ElmtConfig(ePrism, 7, true, false);
1996  tmp[116] = ElmtConfig(ePrism, 8, true, false);
1997  tmp[117] = ElmtConfig(ePrism, 9, true, false);
1998  tmp[118] = ElmtConfig(ePyramid, 3, true, true);
1999  tmp[119] = ElmtConfig(ePyramid, 4, true, true);
2000  tmp[120] = ElmtConfig(ePyramid, 5, true, true);
2001  tmp[121] = ElmtConfig(ePyramid, 6, true, true);
2002  tmp[122] = ElmtConfig(ePyramid, 7, true, true);
2003  tmp[123] = ElmtConfig(ePyramid, 8, true, true);
2004  tmp[124] = ElmtConfig(ePyramid, 9, true, true);
2005  tmp[125] = ElmtConfig(ePyramid, 3, true, false);
2006  tmp[126] = ElmtConfig(ePyramid, 4, true, false);
2007  tmp[127] = ElmtConfig(ePyramid, 5, true, false);
2008  tmp[128] = ElmtConfig(ePyramid, 6, true, false);
2009  tmp[129] = ElmtConfig(ePyramid, 7, true, false);
2010  tmp[130] = ElmtConfig(ePyramid, 7, true, false);
2011  tmp[131] = ElmtConfig(ePyramid, 8, true, false);
2012 
2013  return tmp;
2014 }
Basic information about an element.
Definition: ElementConfig.h:49

◆ GetNnodes()

int Nektar::Utilities::InputGmsh::GetNnodes ( unsigned int  InputGmshEntity)
private

For a given msh ID, return the corresponding number of nodes.

Definition at line 1162 of file InputGmsh.cpp.

References Nektar::LibUtilities::eHexahedron, elmMap, Nektar::LibUtilities::eNodalTriEvenlySpaced, Nektar::LibUtilities::ePoint, Nektar::LibUtilities::ePrism, Nektar::LibUtilities::ePyramid, Nektar::LibUtilities::eQuadrilateral, Nektar::LibUtilities::eSegment, Nektar::LibUtilities::eTetrahedron, Nektar::LibUtilities::eTriangle, Nektar::NekMeshUtils::Point::GetNumNodes(), Nektar::NekMeshUtils::Pyramid::GetNumNodes(), Nektar::NekMeshUtils::Line::GetNumNodes(), Nektar::NekMeshUtils::Prism::GetNumNodes(), Nektar::NekMeshUtils::Tetrahedron::GetNumNodes(), Nektar::NekMeshUtils::Quadrilateral::GetNumNodes(), Nektar::NekMeshUtils::Triangle::GetNumNodes(), and Nektar::NekMeshUtils::Hexahedron::GetNumNodes().

Referenced by ReadNextElement().

1163 {
1164  int nNodes;
1165 
1166  auto it = elmMap.find(InputGmshEntity);
1167 
1168  if (it == elmMap.end())
1169  {
1170  cerr << "Unknown element type " << InputGmshEntity << endl;
1171  abort();
1172  }
1173 
1174  switch (it->second.m_e)
1175  {
1176  case LibUtilities::ePoint:
1177  nNodes = Point::GetNumNodes(it->second);
1178  break;
1180  nNodes = Line::GetNumNodes(it->second);
1181  break;
1183  nNodes = Triangle::GetNumNodes(it->second);
1184  break;
1186  nNodes = Quadrilateral::GetNumNodes(it->second);
1187  break;
1189  nNodes = Tetrahedron::GetNumNodes(it->second);
1190  it->second.m_faceCurveType = LibUtilities::eNodalTriEvenlySpaced;
1191  break;
1193  nNodes = Pyramid::GetNumNodes(it->second);
1194  break;
1195  case LibUtilities::ePrism:
1196  nNodes = Prism::GetNumNodes(it->second);
1197  break;
1199  nNodes = Hexahedron::GetNumNodes(it->second);
1200  break;
1201  default:
1202  cerr << "Unknown element type!" << endl;
1203  abort();
1204  break;
1205  }
1206 
1207  return nNodes;
1208 }
static NEKMESHUTILS_EXPORT unsigned int GetNumNodes(ElmtConfig pConf)
Return the number of nodes defining a quadrilateral.
static NEKMESHUTILS_EXPORT unsigned int GetNumNodes(ElmtConfig pConf)
Return the number of nodes defining a line.
Definition: Line.cpp:187
static NEKMESHUTILS_EXPORT unsigned int GetNumNodes(ElmtConfig pConf)
Return the number of nodes defining a prism.
Definition: Prism.cpp:233
static NEKMESHUTILS_EXPORT unsigned int GetNumNodes(ElmtConfig pConf)
Return the number of nodes defining a triangle.
Definition: Triangle.cpp:159
static NEKMESHUTILS_EXPORT unsigned int GetNumNodes(ElmtConfig pConf)
Return the number of nodes defining a hexahedron.
Definition: Hexahedron.cpp:272
static NEKMESHUTILS_EXPORT unsigned int GetNumNodes(ElmtConfig pConf)
Return the number of nodes defining a tetrahedron.
static NEKMESHUTILS_EXPORT unsigned int GetNumNodes(ElmtConfig pConf)
Return the number of nodes defining a pyramid.
Definition: Pyramid.cpp:176
static NEKMESHUTILS_EXPORT unsigned int GetNumNodes(ElmtConfig pConf)
Return the number of nodes defining a point (i.e. return 1).
Definition: Point.cpp:67
2D Evenly-spaced points on a Triangle
Definition: PointsType.h:71
static std::map< unsigned int, NekMeshUtils::ElmtConfig > elmMap
Definition: InputGmsh.h:67

◆ HexReordering()

vector< int > Nektar::Utilities::InputGmsh::HexReordering ( NekMeshUtils::ElmtConfig  conf)
staticprivate

Create a reordering for hexahedra.

Definition at line 1742 of file InputGmsh.cpp.

References Nektar::StdRegions::eDir1BwdDir1_Dir2FwdDir2, Nektar::StdRegions::eDir1FwdDir1_Dir2FwdDir2, Nektar::StdRegions::eDir1FwdDir2_Dir2FwdDir1, Nektar::Utilities::hexTensorNodeOrdering(), Nektar::NekMeshUtils::ElmtConfig::m_faceNodes, Nektar::NekMeshUtils::ElmtConfig::m_order, Nektar::NekMeshUtils::ElmtConfig::m_volumeNodes, and Nektar::Utilities::quadTensorNodeOrdering().

Referenced by CreateReordering().

1743 {
1744  const int order = conf.m_order;
1745  const int n = order - 1;
1746  const int n2 = n * n;
1747  int i, j, k;
1748 
1749  vector<int> mapping;
1750 
1751  // Map taking Gmsh edges to Nektar++ edges.
1752  static int gmshToNekEdge[12] = {0, -3, 4, 1, 5, 2, 6, 7, 8, -11, 9, 10};
1753 
1754  // Push back vertices.
1755  mapping.resize(8);
1756  for (i = 0; i < 8; ++i)
1757  {
1758  mapping[i] = i;
1759  }
1760 
1761  if (order == 1)
1762  {
1763  return mapping;
1764  }
1765 
1766  // Curvilinear edges
1767  mapping.resize(8 + 12 * n);
1768 
1769  // Reorder edges.
1770  int cnt = 8, offset;
1771  for (i = 0; i < 12; ++i)
1772  {
1773  int edge = gmshToNekEdge[i];
1774  offset = 8 + n * abs(edge);
1775 
1776  if (edge < 0)
1777  {
1778  for (int j = 0; j < n; ++j)
1779  {
1780  mapping[offset + n - j - 1] = cnt++;
1781  }
1782  }
1783  else
1784  {
1785  for (int j = 0; j < n; ++j)
1786  {
1787  mapping[offset + j] = cnt++;
1788  }
1789  }
1790  }
1791 
1792  if (conf.m_faceNodes == false || n2 == 0)
1793  {
1794  return mapping;
1795  }
1796 
1797  // Curvilinear face nodes.
1798  mapping.resize(8 + 12 * n + 6 * n2);
1799 
1800  // Map which takes Gmsh -> Nektar++ faces in the local element.
1801  static int gmsh2NekFace[6] = {0, 1, 4, 2, 3, 5};
1802 
1803  // Map which defines orientation between Gmsh and Nektar++ faces.
1804  StdRegions::Orientation faceOrient[6] = {
1810  StdRegions::eDir1FwdDir1_Dir2FwdDir2};
1811 
1812  for (i = 0; i < 6; ++i)
1813  {
1814  int face = gmsh2NekFace[i];
1815  int offset2 = 8 + 12 * n + i * n2;
1816  offset = 8 + 12 * n + face * n2;
1817 
1818  // Create a list of interior face nodes for this face only.
1819  vector<int> faceNodes(n2);
1820  for (j = 0; j < n2; ++j)
1821  {
1822  faceNodes[j] = offset2 + j;
1823  }
1824 
1825  // Now get the reordering of this face, which puts Gmsh
1826  // recursive ordering into Nektar++ row-by-row order.
1827  vector<int> tmp = quadTensorNodeOrdering(faceNodes, n);
1828 
1829  // Finally reorient the face according to the geometry
1830  // differences.
1831  if (faceOrient[i] == StdRegions::eDir1FwdDir1_Dir2FwdDir2)
1832  {
1833  // Orientation is the same, just copy.
1834  for (j = 0; j < n2; ++j)
1835  {
1836  mapping[offset + j] = tmp[j];
1837  }
1838  }
1839  else if (faceOrient[i] == StdRegions::eDir1FwdDir2_Dir2FwdDir1)
1840  {
1841  // Tranposed faces
1842  for (j = 0; j < n; ++j)
1843  {
1844  for (k = 0; k < n; ++k)
1845  {
1846  mapping[offset + j * n + k] = tmp[k * n + j];
1847  }
1848  }
1849  }
1850  else if (faceOrient[i] == StdRegions::eDir1BwdDir1_Dir2FwdDir2)
1851  {
1852  for (j = 0; j < n; ++j)
1853  {
1854  for (k = 0; k < n; ++k)
1855  {
1856  mapping[offset + j * n + k] = tmp[j * n + (n - k - 1)];
1857  }
1858  }
1859  }
1860  }
1861 
1862  if (conf.m_volumeNodes == false)
1863  {
1864  return mapping;
1865  }
1866 
1867  const int totPoints = (order + 1) * (order + 1) * (order + 1);
1868  vector<int> interior;
1869  for (i = 8 + 12 * n + 6 * n2; i < totPoints; ++i)
1870  {
1871  interior.push_back(i);
1872  }
1873 
1874  interior = hexTensorNodeOrdering(interior, order - 1);
1875  mapping.insert(mapping.end(), interior.begin(), interior.end());
1876 
1877  return mapping;
1878 }
std::vector< int > quadTensorNodeOrdering(const std::vector< int > &nodes, int n)
Reorder Gmsh nodes so that they appear in a tensor product format suitable for the interior of a Nekt...
Definition: InputGmsh.cpp:92
std::vector< int > hexTensorNodeOrdering(const std::vector< int > &nodes, int n)
Reorder Gmsh nodes so that they appear in a "tensor product" format suitable for the interior of a Ne...
Definition: InputGmsh.cpp:539

◆ LineReordering()

vector< int > Nektar::Utilities::InputGmsh::LineReordering ( NekMeshUtils::ElmtConfig  conf)
staticprivate

Definition at line 1258 of file InputGmsh.cpp.

References Nektar::NekMeshUtils::ElmtConfig::m_order.

Referenced by CreateReordering().

1259 {
1260  const int order = conf.m_order;
1261 
1262  vector<int> mapping(order+1);
1263  for(int i = 0; i < order+1; i++)
1264  {
1265  mapping[i] = i;
1266  }
1267 
1268  return mapping;
1269 }

◆ PrismReordering()

vector< int > Nektar::Utilities::InputGmsh::PrismReordering ( NekMeshUtils::ElmtConfig  conf)
staticprivate

Create a reordering for prisms.

Note that whilst Gmsh MSH files have the capability to support high-order prisms, presently Gmsh does not seem to be capable of generating higher than second-order prismatic meshes, so most of the following is untested.

Definition at line 1523 of file InputGmsh.cpp.

References Nektar::NekMeshUtils::HOTriangle< T >::Align(), Nektar::NekMeshUtils::HOQuadrilateral< T >::Align(), Nektar::NekMeshUtils::ElmtConfig::m_faceNodes, Nektar::NekMeshUtils::ElmtConfig::m_order, Nektar::NekMeshUtils::ElmtConfig::m_volumeNodes, Nektar::Utilities::prismTensorNodeOrdering(), Nektar::Utilities::quadTensorNodeOrdering(), Nektar::NekMeshUtils::HOTriangle< T >::surfVerts, Nektar::NekMeshUtils::HOQuadrilateral< T >::surfVerts, and Nektar::Utilities::triTensorNodeOrdering().

Referenced by CreateReordering().

1524 {
1525  const int order = conf.m_order;
1526  const int n = order - 1;
1527 
1528  int i;
1529  vector<int> mapping(6);
1530 
1531  // To get from Gmsh -> Nektar++ prism, coordinates axes are
1532  // different; need to mirror in the triangular faces, and then
1533  // reorder vertices to make ordering anticlockwise on base quad.
1534  static int nekToGmshVerts[6] = {3, 4, 1, 0, 5, 2};
1535  // Inverse (gmsh vert -> Nektar++ vert): 3->0, 4->1, 1->2, 0->3, 5->4, 2->5
1536 
1537  for (i = 0; i < 6; ++i)
1538  {
1539  mapping[i] = nekToGmshVerts[i];
1540  }
1541 
1542  if (order == 1)
1543  {
1544  return mapping;
1545  }
1546 
1547  // Curvilinear edges.
1548  mapping.resize(6 + 9 * n);
1549 
1550  // Nektar++ edges:
1551  // 0 = 1 = 2 = 3 = 4 = 5 = 6 = 7 = 8 =
1552  // {0,1}, {1,2}, {3,2}, {0,3}, {0,4}, {1,4}, {2,5}, {3,5}, {4,5}
1553  // Gmsh edges (from Geo/MPrism.h of Gmsh source):
1554  // {0,1}, {0,2}, {0,3}, {1,2}, {1,4}, {2,5}, {3,4}, {3,5}, {4,5}
1555  // Apply inverse of gmshToNekVerts map:
1556  // {3,2}, {3,5}, {3,0}, {2,5}, {2,1}, {5,4}, {0,1}, {0,4}, {1,4}
1557  // Nektar++ mapping (negative indicates reverse orientation):
1558  // = 2 = 7 = -3 = 6 = -1 = -8 = 0 = 4 = 5
1559  static int gmshToNekEdge[9] = {2, 7, 3, 6, 1, 8, 0, 4, 5};
1560  static int gmshToNekRev[9] = {0, 0, 1, 0, 1, 1, 0, 0, 0};
1561 
1562  // Reorder edges.
1563  int offset, cnt = 6;
1564  for (i = 0; i < 9; ++i)
1565  {
1566  offset = 6 + n * gmshToNekEdge[i];
1567 
1568  if (gmshToNekRev[i])
1569  {
1570  for (int j = 0; j < n; ++j)
1571  {
1572  mapping[offset + n - j - 1] = cnt++;
1573  }
1574  }
1575  else
1576  {
1577  for (int j = 0; j < n; ++j)
1578  {
1579  mapping[offset + j] = cnt++;
1580  }
1581  }
1582  }
1583 
1584  if (conf.m_faceNodes == false)
1585  {
1586  return mapping;
1587  }
1588 
1589  int nTriInt = n * (n - 1) / 2;
1590  int nQuadInt = n * n;
1591 
1592  // Nektar++ faces:
1593  // 0 = {0,1,2,3}, 1 = {0,1,4}, 2 = {1,2,5,4}, 3 = {3,2,5}, 4 = {0,3,5,4}
1594  // Gmsh faces (from Geo/MPrism.h of Gmsh source):
1595  // {0,2,1}, {3,4,5}, {0,1,4,3}, {0,3,5,2}, {1,2,5,4}
1596  // Apply inverse of gmshToNekVerts map:
1597  // {3,5,2}, {0,1,4}, {3,2,1,0}, {3,0,4,5}, {2,5,4,1}
1598  // = 3 = 1 = 0 = 4 = 2
1599  // This gives gmsh -> Nektar++ faces:
1600  static int gmshToNekFace[5] = {3, 1, 0, 4, 2};
1601 
1602  // Face offsets
1603  vector<int> offsets(5), offsets2(5);
1604  offset = 6 + 9 * n;
1605 
1606  // Offsets in the gmsh order: face ordering is TTQQQ
1607  offsets[0] = offset;
1608  offsets[1] = offset + nTriInt;
1609  offsets[2] = offset + 2 * nTriInt;
1610  offsets[3] = offset + 2 * nTriInt + nQuadInt;
1611  offsets[4] = offset + 2 * nTriInt + 2 * nQuadInt;
1612 
1613  // Offsets in the Nektar++ order: face ordering is QTQTQ
1614  offsets2[0] = offset;
1615  offsets2[1] = offset + nQuadInt;
1616  offsets2[2] = offset + nQuadInt + nTriInt;
1617  offsets2[3] = offset + 2 * nQuadInt + nTriInt;
1618  offsets2[4] = offset + 2 * nQuadInt + 2 * nTriInt;
1619 
1620  mapping.resize(6 + 9 * n + 3 * nQuadInt + 2 * nTriInt);
1621 
1622  offset = 6 + 9 * n;
1623 
1624  vector<int> triVertId(3);
1625  triVertId[0] = 0;
1626  triVertId[1] = 1;
1627  triVertId[2] = 2;
1628 
1629  vector<int> quadVertId(4);
1630  quadVertId[0] = 0;
1631  quadVertId[1] = 1;
1632  quadVertId[2] = 2;
1633  quadVertId[3] = 3;
1634 
1635  for (i = 0; i < 5; ++i)
1636  {
1637  int face = gmshToNekFace[i];
1638  int offset2 = offsets[i];
1639  offset = offsets2[face];
1640 
1641  bool tri = i < 2;
1642  int nFacePts = tri ? nTriInt : nQuadInt;
1643 
1644  if (nFacePts == 0)
1645  {
1646  continue;
1647  }
1648 
1649  // Create a list of interior face nodes for this face only.
1650  vector<int> faceNodes(nFacePts);
1651  vector<int> toAlign(tri ? 3 : 4);
1652  for (int j = 0; j < nFacePts; ++j)
1653  {
1654  faceNodes[j] = offset2 + j;
1655  }
1656 
1657  if (tri)
1658  {
1659  // Now get the reordering of this face, which puts Gmsh
1660  // recursive ordering into Nektar++ row-by-row order.
1661  vector<int> tmp = triTensorNodeOrdering(faceNodes, n - 1);
1662  HOTriangle<int> hoTri(triVertId, tmp);
1663 
1664  // Apply reorientation
1665  if (i == 0)
1666  {
1667  // Triangle verts {0,2,1} --> {0,1,2}
1668  toAlign[0] = 0;
1669  toAlign[1] = 2;
1670  toAlign[2] = 1;
1671  hoTri.Align(toAlign);
1672  }
1673 
1674  // Fill in mapping.
1675  for (int j = 0; j < nTriInt; ++j)
1676  {
1677  mapping[offset + j] = hoTri.surfVerts[j];
1678  }
1679  }
1680  else
1681  {
1682  vector<int> tmp = quadTensorNodeOrdering(faceNodes, n);
1683  HOQuadrilateral<int> hoQuad(quadVertId, tmp);
1684 
1685  // Apply reorientation
1686  if (i == 2)
1687  {
1688  toAlign[0] = 3;
1689  toAlign[1] = 2;
1690  toAlign[2] = 1;
1691  toAlign[3] = 0;
1692  }
1693  else if (i == 3)
1694  {
1695  toAlign[0] = 1;
1696  toAlign[1] = 0;
1697  toAlign[2] = 3;
1698  toAlign[3] = 2;
1699  }
1700  else if (i == 4)
1701  {
1702  toAlign[0] = 3;
1703  toAlign[1] = 0;
1704  toAlign[2] = 1;
1705  toAlign[3] = 2;
1706  }
1707 
1708  hoQuad.Align(toAlign);
1709 
1710  // Fill in mapping.
1711  for (int j = 0; j < nQuadInt; ++j)
1712  {
1713  mapping[offset + j] = hoQuad.surfVerts[j];
1714  }
1715  }
1716  }
1717 
1718  if (conf.m_volumeNodes == false)
1719  {
1720  return mapping;
1721  }
1722 
1723  // Interior points
1724  offset = offsets[4] + nQuadInt;
1725  vector<int> intPoints, tmp;
1726 
1727  for (int i = offset; i < (order+1) * (order+1) * (order+2) / 2; ++i)
1728  {
1729  intPoints.push_back(i);
1730  }
1731 
1732  // Reorder interior points
1733  tmp = prismTensorNodeOrdering(intPoints, order - 1);
1734  mapping.insert(mapping.end(), tmp.begin(), tmp.end());
1735 
1736  return mapping;
1737 }
std::vector< int > prismTensorNodeOrdering(const std::vector< int > &nodes, int n)
Reorder Gmsh nodes so that they appear in a "tensor product" format suitable for the interior of a Ne...
Definition: InputGmsh.cpp:463
std::vector< int > triTensorNodeOrdering(const std::vector< int > &nodes, int n)
Reorder Gmsh nodes so that they appear in a "tensor product" format suitable for the interior of a Ne...
Definition: InputGmsh.cpp:169
std::vector< int > quadTensorNodeOrdering(const std::vector< int > &nodes, int n)
Reorder Gmsh nodes so that they appear in a tensor product format suitable for the interior of a Nekt...
Definition: InputGmsh.cpp:92
A lightweight struct for dealing with high-order triangle alignment.
Definition: HOAlignment.h:49
A lightweight struct for dealing with high-order quadrilateral alignment.
Definition: HOAlignment.h:208

◆ Process()

void Nektar::Utilities::InputGmsh::Process ( )
virtual

Gmsh file contains a list of nodes and their coordinates, along with a list of elements and those nodes which define them. We read in and store the list of nodes in #m_node and store the list of elements in #m_element. Each new element is supplied with a list of entries from m_node which defines the element. Finally some mesh statistics are printed.

Parameters
pFilenameFilename of Gmsh file to read.

Implements Nektar::NekMeshUtils::Module.

Definition at line 728 of file InputGmsh.cpp.

References ASSERTL0, m_maxTagId, Nektar::NekMeshUtils::Module::m_mesh, Nektar::NekMeshUtils::InputModule::m_mshFile, m_version, Nektar::Utilities::GmshEntity::maxX, Nektar::Utilities::GmshEntity::maxY, Nektar::Utilities::GmshEntity::maxZ, Nektar::Utilities::GmshEntity::minX, Nektar::Utilities::GmshEntity::minY, Nektar::Utilities::GmshEntity::minZ, Nektar::NekMeshUtils::InputModule::OpenStream(), Nektar::Utilities::GmshEntity::physicalTags, Nektar::NekMeshUtils::Module::ProcessComposites(), Nektar::NekMeshUtils::Module::ProcessEdges(), Nektar::NekMeshUtils::Module::ProcessElements(), Nektar::NekMeshUtils::Module::ProcessFaces(), Nektar::NekMeshUtils::Module::ProcessVertices(), ReadNextElement(), ReadNextNode(), ReadNextNodeBlock(), and Nektar::LibUtilities::ShapeTypeMap.

729 {
730  // Open the file stream.
731  OpenStream();
732 
733  m_mesh->m_expDim = 0;
734  m_mesh->m_spaceDim = 0;
735  string line;
736  int fileType = 0;
737  int nVBlocks = 0;
738  int nVertices = 0;
739  int nEBlocks = 0;
740  int nElements = 0;
741  int tag = 0;
742  int elm_type = 0;
743  int tmp = 0;
744 
745  if (m_mesh->m_verbose)
746  {
747  cout << "InputGmsh: Start reading file..." << endl;
748  }
749 
750  std::vector<std::map<int, GmshEntity>> entityMap(4);
751 
752  while (!m_mshFile.eof())
753  {
754  getline(m_mshFile, line);
755  stringstream s(line);
756  string word;
757  s >> word;
758 
759  // Process file format.
760  if (word == "$MeshFormat")
761  {
762  getline(m_mshFile, line);
763  stringstream s(line);
764  s >> m_version;
765  s >> fileType;
766  ASSERTL0(fileType == 0, "Cannot read binary Gmsh files.")
767  ASSERTL0(m_version <= 4.1, ".msh file format versions greater than 4.1 are not currently supported.")
768  }
769  // Process entities (v4+)
770  else if (word == "$Entities")
771  {
772  size_t nEntity[4];
773  getline(m_mshFile, line);
774  stringstream s(line);
775 
776  s >> nEntity[0] >> nEntity[1] >> nEntity[2] >> nEntity[3];
777 
778  for (int i = 0; i < 4; ++i)
779  {
780  for (int j = 0; j < nEntity[i]; ++j)
781  {
782  getline(m_mshFile, line);
783  stringstream si(line);
784  GmshEntity ent;
785 
786  int entityId;
787  si >> entityId >> ent.minX >> ent.minY >> ent.minZ;
788 
789  if (i > 0)
790  {
791  si >> ent.maxX >> ent.maxY >> ent.maxZ;
792  }
793 
794  int nPhysTags, tmp;
795  si >> nPhysTags;
796 
797  for (int k = 0; k < nPhysTags; ++k)
798  {
799  si >> tmp;
800  ent.physicalTags.push_back(tmp);
801  }
802 
803  entityMap[i][entityId] = ent;
804  }
805  }
806  }
807  // Process nodes.
808  else if (word == "$Nodes")
809  {
810  getline(m_mshFile, line);
811  stringstream s(line);
812 
813  if (m_version >= 4.0)
814  {
815  s >> nVBlocks;
816 
817  for (int i = 0; i < nVBlocks; ++i)
818  {
819  getline(m_mshFile, line);
820  stringstream si(line);
821  si >> tmp >> tmp >> tmp >> nVertices;
822 
823  if (m_version == 4.0)
824  {
825  for (int i = 0; i < nVertices; ++i)
826  {
827  ReadNextNode();
828  }
829  }
830  else if (m_version == 4.1)
831  {
832  ReadNextNodeBlock(nVertices);
833  }
834  }
835  }
836  else
837  {
838  s >> nVertices;
839 
840  for (int i = 0; i < nVertices; ++i)
841  {
842  ReadNextNode();
843  }
844  }
845  }
846  // Process elements
847  else if (word == "$Elements")
848  {
849  getline(m_mshFile, line);
850  stringstream s(line);
851 
852  if (m_version >= 4.0)
853  {
854  s >> nEBlocks;
855 
856  for (int i = 0; i < nEBlocks; ++i)
857  {
858  getline(m_mshFile, line);
859  stringstream si(line);
860 
861  int tagDim;
862  if (m_version == 4.0)
863  {
864  si >> tag >> tagDim >> elm_type >> nElements;
865  }
866  else
867  {
868  si >> tagDim >> tag >> elm_type >> nElements;
869  }
870  // Query tag in map & don't bother constructing non-physical
871  // surfaces.
872  std::vector<int> physIds = entityMap[tagDim][tag].physicalTags;
873 
874  if (physIds.size() == 0)
875  {
876  for (int j = 0; j < nElements; ++j)
877  {
878  getline(m_mshFile, line);
879  }
880  }
881  else
882  {
883  tag = physIds[0];
884  for (int j = 0; j < nElements; ++j)
885  {
886  ReadNextElement(tag, elm_type);
887  }
888  }
889 
890  }
891  }
892  else
893  {
894  s >> nElements;
895  for (int i = 0; i < nElements; ++i)
896  {
897  ReadNextElement();
898  }
899  }
900  }
901  }
902  m_mshFile.reset();
903 
904  // Go through element and remap tags if necessary.
905  map<int, map<LibUtilities::ShapeType, int> > compMap;
906 
907  for (int i = 0; i < m_mesh->m_element[m_mesh->m_expDim].size(); ++i)
908  {
909  ElementSharedPtr el = m_mesh->m_element[m_mesh->m_expDim][i];
910  LibUtilities::ShapeType type = el->GetConf().m_e;
911 
912  vector<int> tags = el->GetTagList();
913  int tag = tags[0];
914 
915  auto cIt = compMap.find(tag);
916 
917  if (cIt == compMap.end())
918  {
919  compMap[tag][type] = tag;
920  continue;
921  }
922 
923  // Reset tag for this element.
924  auto sIt = cIt->second.find(type);
925  if (sIt == cIt->second.end())
926  {
927  m_maxTagId++;
928  cIt->second[type] = m_maxTagId;
929  tags[0] = m_maxTagId;
930  el->SetTagList(tags);
931  }
932  else if (sIt->second != tag)
933  {
934  tags[0] = sIt->second;
935  el->SetTagList(tags);
936  }
937  }
938 
939  bool printInfo = false;
940  for (auto &cIt : compMap)
941  {
942  if (cIt.second.size() > 1)
943  {
944  printInfo = true;
945  break;
946  }
947  }
948 
949  if (printInfo)
950  {
951  cout << "Multiple elements in composite detected; remapped:" << endl;
952  for (auto &cIt : compMap)
953  {
954  if (cIt.second.size() > 1)
955  {
956  auto sIt = cIt.second.begin();
957  cout << "- Tag " << cIt.first << " => " << sIt->second << " ("
958  << LibUtilities::ShapeTypeMap[sIt->first] << ")";
959  sIt++;
960 
961  for (; sIt != cIt.second.end(); ++sIt)
962  {
963  cout << ", " << sIt->second << " ("
964  << LibUtilities::ShapeTypeMap[sIt->first] << ")";
965  }
966 
967  cout << endl;
968  }
969  }
970  }
971 
972  // Process rest of mesh.
973  ProcessVertices();
974  ProcessEdges();
975  ProcessFaces();
976  ProcessElements();
978 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
io::filtering_istream m_mshFile
Input stream.
void ReadNextNodeBlock(int nVertices=0)
Definition: InputGmsh.cpp:983
const char *const ShapeTypeMap[]
Definition: ShapeType.hpp:67
NEKMESHUTILS_EXPORT void OpenStream()
Open a file for input.
virtual NEKMESHUTILS_EXPORT void ProcessFaces(bool ReprocessFaces=true)
Extract element faces.
std::shared_ptr< Element > ElementSharedPtr
Definition: Edge.h:49
virtual NEKMESHUTILS_EXPORT void ProcessElements()
Generate element IDs.
void ReadNextElement(int tag=0, int elm_type=0)
Definition: InputGmsh.cpp:1069
virtual NEKMESHUTILS_EXPORT void ProcessVertices()
Extract element vertices.
virtual NEKMESHUTILS_EXPORT void ProcessEdges(bool ReprocessEdges=true)
Extract element edges.
virtual NEKMESHUTILS_EXPORT void ProcessComposites()
Generate composites.

◆ QuadReordering()

vector< int > Nektar::Utilities::InputGmsh::QuadReordering ( NekMeshUtils::ElmtConfig  conf)
staticprivate

Create a reordering for quadrilaterals.

Definition at line 1323 of file InputGmsh.cpp.

References Nektar::NekMeshUtils::ElmtConfig::m_faceNodes, Nektar::NekMeshUtils::ElmtConfig::m_order, and Nektar::Utilities::quadTensorNodeOrdering().

Referenced by CreateReordering().

1324 {
1325  const int order = conf.m_order;
1326  const int n = order - 1;
1327 
1328  // Copy vertices.
1329  vector<int> mapping(4);
1330  for (int i = 0; i < 4; ++i)
1331  {
1332  mapping[i] = i;
1333  }
1334 
1335  if (order == 1)
1336  {
1337  return mapping;
1338  }
1339 
1340  // Curvilinear edges.
1341  mapping.resize(4 + 4 * n);
1342 
1343  for (int i = 4; i < 4 + 4 * n; ++i)
1344  {
1345  mapping[i] = i;
1346  }
1347 
1348  if (!conf.m_faceNodes)
1349  {
1350  return mapping;
1351  }
1352 
1353  // Interior nodes.
1354  vector<int> interior(n * n);
1355  for (int i = 0; i < interior.size(); ++i)
1356  {
1357  interior[i] = i + 4 + 4 * n;
1358  }
1359 
1360  if (interior.size() > 0)
1361  {
1362  interior = quadTensorNodeOrdering(interior, n);
1363  }
1364  mapping.insert(mapping.end(), interior.begin(), interior.end());
1365  return mapping;
1366 }
std::vector< int > quadTensorNodeOrdering(const std::vector< int > &nodes, int n)
Reorder Gmsh nodes so that they appear in a tensor product format suitable for the interior of a Nekt...
Definition: InputGmsh.cpp:92

◆ ReadNextElement()

void Nektar::Utilities::InputGmsh::ReadNextElement ( int  tag = 0,
int  elm_type = 0 
)
private

Read in next element

Definition at line 1069 of file InputGmsh.cpp.

References Nektar::LibUtilities::NekFactory< tKey, tBase, tParam >::CreateInstance(), CreateReordering(), elmMap, Nektar::NekMeshUtils::GetElementFactory(), GetNnodes(), m_idMap, m_maxTagId, Nektar::NekMeshUtils::Module::m_mesh, Nektar::NekMeshUtils::InputModule::m_mshFile, m_orderingMap, and m_version.

Referenced by Process().

1070 {
1071  string line;
1072  getline(m_mshFile, line);
1073  stringstream st(line);
1074  int id = 0, num_tag = 0, num_nodes = 0;
1075 
1076  st >> id;
1077  id -= 1; // counter starts at 0
1078 
1079  if (m_version < 4.0)
1080  {
1081  st >> elm_type >> num_tag;
1082  }
1083 
1084  auto it = elmMap.find(elm_type);
1085  if (it == elmMap.end())
1086  {
1087  cerr << "Error: element type " << elm_type << " not supported" << endl;
1088  abort();
1089  }
1090 
1091  // Read element tags (version 2 only)
1092  vector<int> tags;
1093  for (int j = 0; j < num_tag; ++j)
1094  {
1095  int tag = 0;
1096  st >> tag;
1097  tags.push_back(tag);
1098  }
1099  if (m_version >= 4.0)
1100  {
1101  tags.push_back(tag);
1102  }
1103  tags.resize(1);
1104 
1105  m_maxTagId = max(m_maxTagId, tags[0]);
1106 
1107  // Read element node list
1108  vector<NodeSharedPtr> nodeList;
1109  num_nodes = GetNnodes(elm_type);
1110  for (int k = 0; k < num_nodes; ++k)
1111  {
1112  int node = 0;
1113  st >> node;
1114  node -= 1; // counter starts at 0
1115  if (!m_idMap.size())
1116  {
1117  nodeList.push_back(m_mesh->m_node[node]);
1118  }
1119  else
1120  {
1121  nodeList.push_back(m_mesh->m_node[m_idMap[node]]);
1122  }
1123  }
1124 
1125  // Look up reordering.
1126  auto oIt = m_orderingMap.find(elm_type);
1127 
1128  // If it's not created, then create it.
1129  if (oIt == m_orderingMap.end())
1130  {
1131  oIt =
1132  m_orderingMap.insert(make_pair(elm_type, CreateReordering(elm_type)))
1133  .first;
1134  }
1135 
1136  // Apply reordering map where necessary.
1137  if (oIt->second.size() > 0)
1138  {
1139  vector<int> &mapping = oIt->second;
1140  vector<NodeSharedPtr> tmp = nodeList;
1141  for (int i = 0; i < mapping.size(); ++i)
1142  {
1143  nodeList[i] = tmp[mapping[i]];
1144  }
1145  }
1146 
1147  // Create element
1149  it->second.m_e, it->second, nodeList, tags);
1150 
1151  // Determine mesh expansion dimension
1152  if (E->GetDim() > m_mesh->m_expDim)
1153  {
1154  m_mesh->m_expDim = E->GetDim();
1155  }
1156  m_mesh->m_element[E->GetDim()].push_back(E);
1157 }
io::filtering_istream m_mshFile
Input stream.
ElementFactory & GetElementFactory()
Definition: Element.cpp:44
std::unordered_map< int, std::vector< int > > m_orderingMap
Definition: InputGmsh.h:90
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:144
static std::vector< int > CreateReordering(unsigned int InputGmshEntity)
Create a reordering map for a given element.
Definition: InputGmsh.cpp:1218
std::shared_ptr< Element > ElementSharedPtr
Definition: Edge.h:49
int GetNnodes(unsigned int InputGmshEntity)
Definition: InputGmsh.cpp:1162
std::map< int, int > m_idMap
Definition: InputGmsh.h:84
static std::map< unsigned int, NekMeshUtils::ElmtConfig > elmMap
Definition: InputGmsh.h:67

◆ ReadNextNode()

void Nektar::Utilities::InputGmsh::ReadNextNode ( )
private

Read in next node

Definition at line 1009 of file InputGmsh.cpp.

References Nektar::NekMeshUtils::InputModule::m_mshFile, and SaveNode().

Referenced by Process().

1010 {
1011  string line;
1012  getline(m_mshFile, line);
1013  stringstream st(line);
1014  double x = 0, y = 0, z = 0;
1015  int id = 0;
1016  st >> id >> x >> y >> z;
1017 
1018  SaveNode(id, x, y, z);
1019 }
io::filtering_istream m_mshFile
Input stream.
void SaveNode(int id, NekDouble x=0, NekDouble y=0, NekDouble z=0)
Definition: InputGmsh.cpp:1024

◆ ReadNextNodeBlock()

void Nektar::Utilities::InputGmsh::ReadNextNodeBlock ( int  nVertices = 0)
private

Read in next node block for v4 format

Definition at line 983 of file InputGmsh.cpp.

References Nektar::NekMeshUtils::InputModule::m_mshFile, and SaveNode().

Referenced by Process().

984 {
985  string line;
986  double x = 0, y = 0, z = 0;
987  vector<int> id(nVertices);
988 
989  for (int i = 0; i < nVertices; ++i)
990  {
991  getline(m_mshFile, line);
992  stringstream st(line);
993  st >> id[i];
994  }
995 
996  for (int i = 0; i < nVertices; ++i)
997  {
998  getline(m_mshFile, line);
999  stringstream st(line);
1000  st >> x >> y >> z;
1001 
1002  SaveNode(id[i], x, y, z);
1003  }
1004 }
io::filtering_istream m_mshFile
Input stream.
void SaveNode(int id, NekDouble x=0, NekDouble y=0, NekDouble z=0)
Definition: InputGmsh.cpp:1024

◆ SaveNode()

void Nektar::Utilities::InputGmsh::SaveNode ( int  id,
NekDouble  x = 0,
NekDouble  y = 0,
NekDouble  z = 0 
)
private

Save node into mesh

Definition at line 1024 of file InputGmsh.cpp.

References m_idMap, Nektar::NekMeshUtils::Module::m_mesh, m_prevId, and class_topology::Node.

Referenced by ReadNextNode(), and ReadNextNodeBlock().

1025 {
1026  if ((x * x) > 0.000001 && m_mesh->m_spaceDim < 1)
1027  {
1028  m_mesh->m_spaceDim = 1;
1029  }
1030  if ((y * y) > 0.000001 && m_mesh->m_spaceDim < 2)
1031  {
1032  m_mesh->m_spaceDim = 2;
1033  }
1034  if ((z * z) > 0.000001 && m_mesh->m_spaceDim < 3)
1035  {
1036  m_mesh->m_spaceDim = 3;
1037  }
1038 
1039  id -= 1; // counter starts at 0
1040 
1041  if (!m_idMap.size())
1042  {
1043  if (id - m_prevId == 1)
1044  {
1045  m_prevId = id;
1046  }
1047  else
1048  {
1049  // Build m_idMap so far
1050  for (int i = 0; i < m_mesh->m_node.size(); ++i)
1051  {
1052  m_idMap[i] = i;
1053  }
1054 
1055  m_idMap[id] = m_mesh->m_node.size();
1056  }
1057  }
1058  else
1059  {
1060  m_idMap[id] = m_mesh->m_node.size();
1061  }
1062 
1063  m_mesh->m_node.push_back(std::shared_ptr<Node>(new Node(id, x, y, z)));
1064 }
std::map< int, int > m_idMap
Definition: InputGmsh.h:84

◆ TetReordering()

vector< int > Nektar::Utilities::InputGmsh::TetReordering ( NekMeshUtils::ElmtConfig  conf)
staticprivate

Create a reordering for tetrahedra.

Definition at line 1371 of file InputGmsh.cpp.

References Nektar::NekMeshUtils::HOTriangle< T >::Align(), Nektar::NekMeshUtils::ElmtConfig::m_faceNodes, Nektar::NekMeshUtils::ElmtConfig::m_order, Nektar::NekMeshUtils::ElmtConfig::m_volumeNodes, Nektar::NekMeshUtils::HOTriangle< T >::surfVerts, Nektar::Utilities::tetTensorNodeOrdering(), and Nektar::Utilities::triTensorNodeOrdering().

Referenced by CreateReordering().

1372 {
1373  const int order = conf.m_order;
1374  const int n = order - 1;
1375  const int n2 = n * (n - 1) / 2;
1376 
1377  int i, j;
1378  vector<int> mapping(4);
1379 
1380  // Copy vertices.
1381  for (i = 0; i < 4; ++i)
1382  {
1383  mapping[i] = i;
1384  }
1385 
1386  if (order == 1)
1387  {
1388  return mapping;
1389  }
1390 
1391  // Curvilinear edges.
1392  mapping.resize(4 + 6 * n);
1393 
1394  // Curvilinear edges.
1395  static int gmshToNekEdge[6] = {0, 1, 2, 3, 5, 4};
1396  static int gmshToNekRev[6] = {0, 0, 1, 1, 1, 1};
1397 
1398  // Reorder edges.
1399  int offset, cnt = 4;
1400  for (i = 0; i < 6; ++i)
1401  {
1402  offset = 4 + n * gmshToNekEdge[i];
1403 
1404  if (gmshToNekRev[i])
1405  {
1406  for (int j = 0; j < n; ++j)
1407  {
1408  mapping[offset + n - j - 1] = cnt++;
1409  }
1410  }
1411  else
1412  {
1413  for (int j = 0; j < n; ++j)
1414  {
1415  mapping[offset + j] = cnt++;
1416  }
1417  }
1418  }
1419 
1420  if (conf.m_faceNodes == false || n2 == 0)
1421  {
1422  return mapping;
1423  }
1424 
1425  // Curvilinear faces.
1426  mapping.resize(4 + 6 * n + 4 * n2);
1427 
1428  static int gmshToNekFace[4] = {0, 1, 3, 2};
1429 
1430  vector<int> triVertId(3);
1431  triVertId[0] = 0;
1432  triVertId[1] = 1;
1433  triVertId[2] = 2;
1434 
1435  // Loop over Gmsh faces
1436  for (i = 0; i < 4; ++i)
1437  {
1438  int face = gmshToNekFace[i];
1439  int offset2 = 4 + 6 * n + i * n2;
1440  offset = 4 + 6 * n + face * n2;
1441 
1442  // Create a list of interior face nodes for this face only.
1443  vector<int> faceNodes(n2);
1444  vector<int> toAlign(3);
1445  for (j = 0; j < n2; ++j)
1446  {
1447  faceNodes[j] = offset2 + j;
1448  }
1449 
1450  // Now get the reordering of this face, which puts Gmsh
1451  // recursive ordering into Nektar++ row-by-row order.
1452  vector<int> tmp = triTensorNodeOrdering(faceNodes, n - 1);
1453  HOTriangle<int> hoTri(triVertId, tmp);
1454 
1455  // Apply reorientation
1456  if (i == 0 || i == 2)
1457  {
1458  // Triangle verts {0,2,1} --> {0,1,2}
1459  toAlign[0] = 0;
1460  toAlign[1] = 2;
1461  toAlign[2] = 1;
1462  hoTri.Align(toAlign);
1463  }
1464  else if (i == 3)
1465  {
1466  // Triangle verts {1,2,0} --> {0,1,2}
1467  toAlign[0] = 1;
1468  toAlign[1] = 2;
1469  toAlign[2] = 0;
1470  hoTri.Align(toAlign);
1471  }
1472 
1473  // Fill in mapping.
1474  for (j = 0; j < n2; ++j)
1475  {
1476  mapping[offset + j] = hoTri.surfVerts[j];
1477  }
1478  }
1479 
1480  if (conf.m_volumeNodes == false)
1481  {
1482  return mapping;
1483  }
1484 
1485  const int nInt = (order - 3) * (order - 2) * (order - 1) / 6;
1486  if (nInt <= 0)
1487  {
1488  return mapping;
1489  }
1490 
1491  if (nInt == 1)
1492  {
1493  mapping.push_back(mapping.size());
1494  return mapping;
1495  }
1496 
1497  int ntot = (order+1)*(order+2)*(order+3)/6;
1498  vector<int> interior;
1499 
1500  for (int i = 4 + 6 * n + 4 * n2; i < ntot; ++i)
1501  {
1502  interior.push_back(i);
1503  }
1504 
1505  if (interior.size() > 0)
1506  {
1507  interior = tetTensorNodeOrdering(interior, order-3);
1508  }
1509 
1510  mapping.insert(mapping.end(), interior.begin(), interior.end());
1511 
1512  return mapping;
1513 }
std::vector< int > triTensorNodeOrdering(const std::vector< int > &nodes, int n)
Reorder Gmsh nodes so that they appear in a "tensor product" format suitable for the interior of a Ne...
Definition: InputGmsh.cpp:169
A lightweight struct for dealing with high-order triangle alignment.
Definition: HOAlignment.h:49
std::vector< int > tetTensorNodeOrdering(const std::vector< int > &nodes, int n)
Reorder Gmsh nodes so that they appear in a "tensor product" format suitable for the interior of a Ne...
Definition: InputGmsh.cpp:284

◆ TriReordering()

vector< int > Nektar::Utilities::InputGmsh::TriReordering ( NekMeshUtils::ElmtConfig  conf)
staticprivate

Create a reordering for triangles.

Definition at line 1274 of file InputGmsh.cpp.

References Nektar::NekMeshUtils::ElmtConfig::m_faceNodes, Nektar::NekMeshUtils::ElmtConfig::m_order, and Nektar::Utilities::triTensorNodeOrdering().

Referenced by CreateReordering().

1275 {
1276  const int order = conf.m_order;
1277  const int n = order - 1;
1278 
1279  // Copy vertices.
1280  vector<int> mapping(3);
1281  for (int i = 0; i < 3; ++i)
1282  {
1283  mapping[i] = i;
1284  }
1285 
1286  if (order == 1)
1287  {
1288  return mapping;
1289  }
1290 
1291  // Curvilinear edges.
1292  mapping.resize(3 + 3 * n);
1293 
1294  for (int i = 3; i < 3 + 3 * n; ++i)
1295  {
1296  mapping[i] = i;
1297  }
1298 
1299  if (!conf.m_faceNodes)
1300  {
1301  return mapping;
1302  }
1303 
1304  // Interior nodes.
1305  vector<int> interior(n * (n - 1) / 2);
1306  for (int i = 0; i < interior.size(); ++i)
1307  {
1308  interior[i] = i + 3 + 3 * n;
1309  }
1310 
1311  if (interior.size() > 0)
1312  {
1313  interior = triTensorNodeOrdering(interior, n - 1);
1314  }
1315 
1316  mapping.insert(mapping.end(), interior.begin(), interior.end());
1317  return mapping;
1318 }
std::vector< int > triTensorNodeOrdering(const std::vector< int > &nodes, int n)
Reorder Gmsh nodes so that they appear in a "tensor product" format suitable for the interior of a Ne...
Definition: InputGmsh.cpp:169

Member Data Documentation

◆ className

ModuleKey Nektar::Utilities::InputGmsh::className
static
Initial value:

ModuleKey for class.

Definition at line 61 of file InputGmsh.h.

◆ elmMap

std::map< unsigned int, ElmtConfig > Nektar::Utilities::InputGmsh::elmMap = InputGmsh::GenElmMap()
static

Element map; takes a msh id to an ElmtConfig object.

Definition at line 67 of file InputGmsh.h.

Referenced by CreateReordering(), GetNnodes(), and ReadNextElement().

◆ m_idMap

std::map<int, int> Nektar::Utilities::InputGmsh::m_idMap
private

Definition at line 84 of file InputGmsh.h.

Referenced by ReadNextElement(), and SaveNode().

◆ m_maxTagId

int Nektar::Utilities::InputGmsh::m_maxTagId
private

Definition at line 86 of file InputGmsh.h.

Referenced by Process(), and ReadNextElement().

◆ m_orderingMap

std::unordered_map<int, std::vector<int> > Nektar::Utilities::InputGmsh::m_orderingMap
private

Definition at line 90 of file InputGmsh.h.

Referenced by ReadNextElement().

◆ m_prevId

int Nektar::Utilities::InputGmsh::m_prevId
private

Definition at line 82 of file InputGmsh.h.

Referenced by SaveNode().

◆ m_version

NekDouble Nektar::Utilities::InputGmsh::m_version
private

Definition at line 80 of file InputGmsh.h.

Referenced by Process(), and ReadNextElement().