Nektar++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Public Member Functions | Static Public Member Functions | Static Public Attributes | Private Member Functions | List of all members
Nektar::Utilities::InputGmsh Class Reference

#include <InputGmsh.h>

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

Public Member Functions

 InputGmsh (MeshSharedPtr m)
 Set up InputGmsh object.
virtual ~InputGmsh ()
virtual void Process ()
- Public Member Functions inherited from Nektar::Utilities::InputModule
 InputModule (FieldSharedPtr p_m)
void AddFile (string fileType, string fileName)
 InputModule (MeshSharedPtr p_m)
void OpenStream ()
 Open a file for input.
- Public Member Functions inherited from Nektar::Utilities::Module
 Module (FieldSharedPtr p_f)
virtual void Process (po::variables_map &vm)=0
void RegisterConfig (string key, string value)
 Register a configuration option with a module.
void PrintConfig ()
 Print out all configuration options for a module.
void SetDefaults ()
 Sets default configuration options for those which have not been set.
bool GetRequireEquiSpaced (void)
void SetRequireEquiSpaced (bool pVal)
void EvaluateTriFieldAtEquiSpacedPts (LocalRegions::ExpansionSharedPtr &exp, const Array< OneD, const NekDouble > &infield, Array< OneD, NekDouble > &outfield)
 Module (MeshSharedPtr p_m)
void RegisterConfig (string key, string value)
void PrintConfig ()
void SetDefaults ()
MeshSharedPtr GetMesh ()
virtual void ProcessVertices ()
 Extract element vertices.

Static Public Member Functions

static ModuleSharedPtr create (MeshSharedPtr m)
 Creates an instance of this class.
static std::map< unsigned int,
ElmtConfig
GenElmMap ()

Static Public Attributes

static ModuleKey className
 ModuleKey for class.
static std::map< unsigned int,
ElmtConfig
elmMap

Private Member Functions

int GetNnodes (unsigned int InputGmshEntity)
vector< int > CreateReordering (unsigned int InputGmshEntity)
 Create a reordering map for a given element.
vector< int > TriReordering (ElmtConfig conf)
 Create a reordering for triangles.
vector< int > QuadReordering (ElmtConfig conf)
 Create a reordering for quadrilaterals.
vector< int > HexReordering (ElmtConfig conf)
 Create a reordering for hexahedra.
vector< int > PrismReordering (ElmtConfig conf)
 Create a reordering for prisms.
vector< int > TetReordering (ElmtConfig conf)
 Create a reordering for tetrahedra.

Additional Inherited Members

- Protected Member Functions inherited from Nektar::Utilities::InputModule
void PrintSummary ()
 Print summary of elements.
void PrintSummary ()
 Print summary of elements.
- Protected Attributes inherited from Nektar::Utilities::InputModule
set< string > m_allowedFiles
std::ifstream m_mshFile
 Input stream.

Detailed Description

Converter for Gmsh files.

Definition at line 48 of file InputGmsh.h.

Constructor & Destructor Documentation

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

Set up InputGmsh object.

Definition at line 162 of file InputGmsh.cpp.

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

Definition at line 167 of file InputGmsh.cpp.

{
}

Member Function Documentation

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

Creates an instance of this class.

Definition at line 56 of file InputGmsh.h.

{
return MemoryManager<InputGmsh>::AllocateSharedPtr(m);
}
vector< int > Nektar::Utilities::InputGmsh::CreateReordering ( unsigned int  InputGmshEntity)
private

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 478 of file InputGmsh.cpp.

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

Referenced by Process().

{
it = elmMap.find(InputGmshEntity);
if (it == elmMap.end())
{
cerr << "Unknown element type " << InputGmshEntity << endl;
abort();
}
// For specific elements, call the appropriate function to perform
// the renumbering.
switch(it->second.m_e)
{
return TriReordering(it->second);
break;
return QuadReordering(it->second);
break;
return TetReordering(it->second);
break;
return PrismReordering(it->second);
break;
return HexReordering(it->second);
break;
default:
break;
}
// Default: no reordering.
vector<int> returnVal;
return returnVal;
}
std::map< unsigned int, ElmtConfig > Nektar::Utilities::InputGmsh::GenElmMap ( )
static

Definition at line 957 of file InputGmsh.cpp.

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

{
using namespace LibUtilities;
std::map<unsigned int, ElmtConfig> tmp;
// Elmt type, order, face, volume
tmp[ 1] = ElmtConfig(eSegment, 1, true, true);
tmp[ 2] = ElmtConfig(eTriangle, 1, true, true);
tmp[ 3] = ElmtConfig(eQuadrilateral, 1, true, true);
tmp[ 4] = ElmtConfig(eTetrahedron, 1, true, true);
tmp[ 5] = ElmtConfig(eHexahedron, 1, true, true);
tmp[ 6] = ElmtConfig(ePrism, 1, true, true);
tmp[ 7] = ElmtConfig(ePyramid, 1, true, true);
tmp[ 8] = ElmtConfig(eSegment, 2, true, true);
tmp[ 9] = ElmtConfig(eTriangle, 2, true, true);
tmp[ 10] = ElmtConfig(eQuadrilateral, 2, true, true);
tmp[ 11] = ElmtConfig(eTetrahedron, 2, true, true);
tmp[ 12] = ElmtConfig(eHexahedron, 2, true, true);
tmp[ 13] = ElmtConfig(ePrism, 2, true, true);
tmp[ 14] = ElmtConfig(ePyramid, 2, true, true);
tmp[ 15] = ElmtConfig(ePoint, 1, true, false);
tmp[ 16] = ElmtConfig(eQuadrilateral, 2, false, false);
tmp[ 17] = ElmtConfig(eHexahedron, 2, false, false);
tmp[ 18] = ElmtConfig(ePrism, 2, false, false);
tmp[ 19] = ElmtConfig(ePyramid, 2, false, false);
tmp[ 20] = ElmtConfig(eTriangle, 3, false, false);
tmp[ 21] = ElmtConfig(eTriangle, 3, true, false);
tmp[ 22] = ElmtConfig(eTriangle, 4, false, false);
tmp[ 23] = ElmtConfig(eTriangle, 4, true, false);
tmp[ 24] = ElmtConfig(eTriangle, 5, false, false);
tmp[ 25] = ElmtConfig(eTriangle, 5, true, false);
tmp[ 26] = ElmtConfig(eSegment, 3, true, false);
tmp[ 27] = ElmtConfig(eSegment, 4, true, false);
tmp[ 28] = ElmtConfig(eSegment, 5, true, false);
tmp[ 29] = ElmtConfig(eTetrahedron, 3, true, true);
tmp[ 30] = ElmtConfig(eTetrahedron, 4, true, true);
tmp[ 31] = ElmtConfig(eTetrahedron, 5, true, true);
tmp[ 32] = ElmtConfig(eTetrahedron, 4, true, false);
tmp[ 33] = ElmtConfig(eTetrahedron, 5, true, false);
tmp[ 36] = ElmtConfig(eQuadrilateral, 3, true, false);
tmp[ 37] = ElmtConfig(eQuadrilateral, 4, true, false);
tmp[ 38] = ElmtConfig(eQuadrilateral, 5, true, false);
tmp[ 39] = ElmtConfig(eQuadrilateral, 3, false, false);
tmp[ 40] = ElmtConfig(eQuadrilateral, 4, false, false);
tmp[ 41] = ElmtConfig(eQuadrilateral, 5, false, false);
tmp[ 42] = ElmtConfig(eTriangle, 6, true, false);
tmp[ 43] = ElmtConfig(eTriangle, 7, true, false);
tmp[ 44] = ElmtConfig(eTriangle, 8, true, false);
tmp[ 45] = ElmtConfig(eTriangle, 9, true, false);
tmp[ 46] = ElmtConfig(eTriangle, 10, true, false);
tmp[ 47] = ElmtConfig(eQuadrilateral, 6, true, false);
tmp[ 48] = ElmtConfig(eQuadrilateral, 7, true, false);
tmp[ 49] = ElmtConfig(eQuadrilateral, 8, true, false);
tmp[ 50] = ElmtConfig(eQuadrilateral, 9, true, false);
tmp[ 51] = ElmtConfig(eQuadrilateral, 10, true, false);
tmp[ 52] = ElmtConfig(eTriangle, 6, false, false);
tmp[ 53] = ElmtConfig(eTriangle, 7, false, false);
tmp[ 54] = ElmtConfig(eTriangle, 8, false, false);
tmp[ 55] = ElmtConfig(eTriangle, 9, false, false);
tmp[ 56] = ElmtConfig(eTriangle, 10, false, false);
tmp[ 57] = ElmtConfig(eQuadrilateral, 6, false, false);
tmp[ 58] = ElmtConfig(eQuadrilateral, 7, false, false);
tmp[ 59] = ElmtConfig(eQuadrilateral, 8, false, false);
tmp[ 60] = ElmtConfig(eQuadrilateral, 9, false, false);
tmp[ 61] = ElmtConfig(eQuadrilateral, 10, false, false);
tmp[ 62] = ElmtConfig(eSegment, 6, true, false);
tmp[ 63] = ElmtConfig(eSegment, 7, true, false);
tmp[ 64] = ElmtConfig(eSegment, 8, true, false);
tmp[ 65] = ElmtConfig(eSegment, 9, true, false);
tmp[ 66] = ElmtConfig(eSegment, 10, true, false);
tmp[ 71] = ElmtConfig(eTetrahedron, 6, true, true);
tmp[ 72] = ElmtConfig(eTetrahedron, 7, true, true);
tmp[ 73] = ElmtConfig(eTetrahedron, 8, true, true);
tmp[ 74] = ElmtConfig(eTetrahedron, 9, true, true);
tmp[ 75] = ElmtConfig(eTetrahedron, 10, true, true);
tmp[ 79] = ElmtConfig(eTetrahedron, 6, true, false);
tmp[ 80] = ElmtConfig(eTetrahedron, 7, true, false);
tmp[ 81] = ElmtConfig(eTetrahedron, 8, true, false);
tmp[ 82] = ElmtConfig(eTetrahedron, 9, true, false);
tmp[ 83] = ElmtConfig(eTetrahedron, 10, true, false);
tmp[ 90] = ElmtConfig(ePrism, 3, true, true);
tmp[ 91] = ElmtConfig(ePrism, 4, true, true);
tmp[ 92] = ElmtConfig(eHexahedron, 3, true, true);
tmp[ 93] = ElmtConfig(eHexahedron, 4, true, true);
tmp[ 94] = ElmtConfig(eHexahedron, 5, true, true);
tmp[ 95] = ElmtConfig(eHexahedron, 6, true, true);
tmp[ 96] = ElmtConfig(eHexahedron, 7, true, true);
tmp[ 97] = ElmtConfig(eHexahedron, 8, true, true);
tmp[ 98] = ElmtConfig(eHexahedron, 9, true, true);
tmp[ 99] = ElmtConfig(eHexahedron, 3, true, false);
tmp[100] = ElmtConfig(eHexahedron, 4, true, false);
tmp[101] = ElmtConfig(eHexahedron, 5, true, false);
tmp[102] = ElmtConfig(eHexahedron, 6, true, false);
tmp[103] = ElmtConfig(eHexahedron, 7, true, false);
tmp[104] = ElmtConfig(eHexahedron, 8, true, false);
tmp[105] = ElmtConfig(eHexahedron, 9, true, false);
tmp[106] = ElmtConfig(ePrism, 5, true, true);
tmp[107] = ElmtConfig(ePrism, 6, true, true);
tmp[108] = ElmtConfig(ePrism, 7, true, true);
tmp[109] = ElmtConfig(ePrism, 8, true, true);
tmp[110] = ElmtConfig(ePrism, 9, true, true);
tmp[111] = ElmtConfig(ePrism, 3, true, false);
tmp[112] = ElmtConfig(ePrism, 4, true, false);
tmp[113] = ElmtConfig(ePrism, 5, true, false);
tmp[114] = ElmtConfig(ePrism, 6, true, false);
tmp[115] = ElmtConfig(ePrism, 7, true, false);
tmp[116] = ElmtConfig(ePrism, 8, true, false);
tmp[117] = ElmtConfig(ePrism, 9, true, false);
tmp[118] = ElmtConfig(ePyramid, 3, true, true);
tmp[119] = ElmtConfig(ePyramid, 4, true, true);
tmp[120] = ElmtConfig(ePyramid, 5, true, true);
tmp[121] = ElmtConfig(ePyramid, 6, true, true);
tmp[122] = ElmtConfig(ePyramid, 7, true, true);
tmp[123] = ElmtConfig(ePyramid, 8, true, true);
tmp[124] = ElmtConfig(ePyramid, 9, true, true);
tmp[125] = ElmtConfig(ePyramid, 3, true, false);
tmp[126] = ElmtConfig(ePyramid, 4, true, false);
tmp[127] = ElmtConfig(ePyramid, 5, true, false);
tmp[128] = ElmtConfig(ePyramid, 6, true, false);
tmp[129] = ElmtConfig(ePyramid, 7, true, false);
tmp[130] = ElmtConfig(ePyramid, 7, true, false);
tmp[131] = ElmtConfig(ePyramid, 8, true, false);
return tmp;
}
int Nektar::Utilities::InputGmsh::GetNnodes ( unsigned int  InputGmshEntity)
private

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

Definition at line 420 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::Utilities::Point::GetNumNodes(), Nektar::Utilities::Line::GetNumNodes(), Nektar::Utilities::Triangle::GetNumNodes(), Nektar::Utilities::Quadrilateral::GetNumNodes(), Nektar::Utilities::Tetrahedron::GetNumNodes(), Nektar::Utilities::Pyramid::GetNumNodes(), Nektar::Utilities::Prism::GetNumNodes(), Nektar::Utilities::Hexahedron::GetNumNodes(), and Nektar::iterator.

Referenced by Process().

{
int nNodes;
it = elmMap.find(InputGmshEntity);
if (it == elmMap.end())
{
cerr << "Unknown element type " << InputGmshEntity << endl;
abort();
}
switch(it->second.m_e)
{
nNodes = Point:: GetNumNodes(it->second);
break;
nNodes = Line:: GetNumNodes(it->second);
break;
nNodes = Triangle:: GetNumNodes(it->second);
break;
nNodes = Quadrilateral::GetNumNodes(it->second);
break;
nNodes = Tetrahedron:: GetNumNodes(it->second);
it->second.m_faceCurveType =
break;
nNodes = Pyramid:: GetNumNodes(it->second);
break;
nNodes = Prism:: GetNumNodes(it->second);
break;
nNodes = Hexahedron:: GetNumNodes(it->second);
break;
default:
cerr << "Unknown element type!" << endl;
abort();
break;
}
return nNodes;
}
vector< int > Nektar::Utilities::InputGmsh::HexReordering ( ElmtConfig  conf)
private

Create a reordering for hexahedra.

Definition at line 807 of file InputGmsh.cpp.

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

Referenced by CreateReordering().

{
const int order = conf.m_order;
const int n = order-1;
const int n2 = n * n;
int i, j, k;
vector<int> mapping;
// Map taking Gmsh edges to Nektar++ edges.
static int gmshToNekEdge[12] = {
0, -3, 4, 1, 5, 2, 6, 7, 8, -11, 9, 10
};
// Push back vertices.
mapping.resize(8);
for (i = 0; i < 8; ++i)
{
mapping[i] = i;
}
if (order == 1)
{
return mapping;
}
// Curvilinear edges
mapping.resize(8 + 12*n);
// Reorder edges.
int cnt = 8, offset;
for (i = 0; i < 12; ++i)
{
int edge = gmshToNekEdge[i];
offset = 8 + n * abs(edge);
if (edge < 0)
{
for (int j = 0; j < n; ++j)
{
mapping[offset+n-j-1] = cnt++;
}
}
else
{
for (int j = 0; j < n; ++j)
{
mapping[offset+j] = cnt++;
}
}
}
if (conf.m_faceNodes == false || n2 == 0)
{
return mapping;
}
// Curvilinear face nodes.
mapping.resize(8 + 12*n + 6*n2);
// Map which takes Gmsh -> Nektar++ faces in the local element.
static int gmsh2NekFace[6] = {0,1,4,2,3,5};
// Map which defines orientation between Gmsh and Nektar++ faces.
StdRegions::Orientation faceOrient[6] = {
StdRegions::eDir1FwdDir1_Dir2FwdDir2
};
for (i = 0; i < 6; ++i)
{
int face = gmsh2NekFace[i];
int offset2 = 8 + 12 * n + i * n2;
offset = 8 + 12 * n + face * n2;
// Create a list of interior face nodes for this face only.
vector<int> faceNodes(n2);
for (j = 0; j < n2; ++j)
{
faceNodes[j] = offset2 + j;
}
// Now get the reordering of this face, which puts Gmsh
// recursive ordering into Nektar++ row-by-row order.
vector<int> tmp = quadTensorNodeOrdering(faceNodes, n);
// Finally reorient the face according to the geometry
// differences.
{
// Orientation is the same, just copy.
for (j = 0; j < n2; ++j)
{
mapping[offset+j] = tmp[j];
}
}
else if (faceOrient[i] == StdRegions::eDir1FwdDir2_Dir2FwdDir1)
{
// Tranposed faces
for (j = 0; j < n; ++j)
{
for (k = 0; k < n; ++k)
{
mapping[offset + j*n + k] = tmp[k*n + j];
}
}
}
else if (faceOrient[i] == StdRegions::eDir1BwdDir1_Dir2FwdDir2)
{
for (j = 0; j < n; ++j)
{
for (k = 0; k < n; ++k)
{
mapping[offset + j*n + k] = tmp[j*n + (n-k-1)];
}
}
}
}
if (conf.m_volumeNodes == false)
{
return mapping;
}
const int totPoints = (order+1) * (order+1) * (order+1);
mapping.resize(totPoints);
// TODO: Fix ordering of volume nodes.
for (i = 8 + 12*n + 6*n2; i < totPoints; ++i)
{
mapping[i] = i;
}
return mapping;
}
vector< int > Nektar::Utilities::InputGmsh::PrismReordering ( ElmtConfig  conf)
private

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 732 of file InputGmsh.cpp.

References Nektar::Utilities::ElmtConfig::m_faceNodes, and Nektar::Utilities::ElmtConfig::m_order.

Referenced by CreateReordering().

{
const int order = conf.m_order;
const int n = order-1;
int i;
vector<int> mapping(6);
// To get from Gmsh -> Nektar++ prism, coordinates axes are
// different; need to mirror in the triangular faces, and then
// reorder vertices to make ordering anticlockwise on base quad.
static int gmshToNekVerts[6] = {3,4,1,0,5,2};
for (i = 0; i < 6; ++i)
{
mapping[i] = gmshToNekVerts[i];
}
if (order == 1)
{
return mapping;
}
// Curvilinear edges.
mapping.resize(6 + 9*n);
static int gmshToNekEdge[9] = {2,7,3,6,1,8,0,4,5};
static int gmshToNekRev [9] = {1,0,1,0,1,1,0,0,0};
// Reorder edges.
int offset, cnt = 6;
for (i = 0; i < 9; ++i)
{
offset = 6 + n * gmshToNekEdge[i];
if (gmshToNekRev[i])
{
for (int j = 0; j < n; ++j)
{
mapping[offset+n-j-1] = cnt++;
}
}
else
{
for (int j = 0; j < n; ++j)
{
mapping[offset+j] = cnt++;
}
}
}
if (conf.m_faceNodes == false)
{
return mapping;
}
if (order > 2)
{
cerr << "Gmsh prisms of order > 2 with face curvature "
<< "not supported in MeshConvert (or indeed Gmsh at"
<< "time of writing)." << endl;
abort();
}
mapping.resize(18);
mapping[15] = 15;
mapping[16] = 17;
mapping[17] = 16;
return mapping;
}
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::Utilities::Module.

Definition at line 182 of file InputGmsh.cpp.

References CreateReordering(), elmMap, Nektar::Utilities::GetElementFactory(), GetNnodes(), Nektar::iterator, Nektar::Utilities::Module::m_mesh, Nektar::Utilities::InputModule::m_mshFile, Nektar::Utilities::InputModule::OpenStream(), Nektar::Utilities::Module::ProcessComposites(), Nektar::Utilities::Module::ProcessEdges(), Nektar::Utilities::Module::ProcessElements(), Nektar::Utilities::Module::ProcessFaces(), Nektar::Utilities::Module::ProcessVertices(), and Nektar::LibUtilities::ShapeTypeMap.

{
// Open the file stream.
m_mesh->m_expDim = 0;
m_mesh->m_spaceDim = 0;
string line;
int nVertices = 0;
int nEntities = 0;
int elm_type = 0;
int prevId = -1;
int maxTagId = -1;
// This map takes each element ID and maps it to a permutation map
// that is required to take Gmsh element node orderings and map them
// to Nektar++ orderings.
boost::unordered_map<int, vector<int> > orderingMap;
boost::unordered_map<int, vector<int> >::iterator oIt;
if (m_mesh->m_verbose)
{
cout << "InputGmsh: Start reading file..." << endl;
}
while (!m_mshFile.eof())
{
getline(m_mshFile, line);
stringstream s(line);
string word;
s >> word;
// Process nodes.
if (word == "$Nodes")
{
getline(m_mshFile, line);
stringstream s(line);
s >> nVertices;
int id = 0;
for (int i = 0; i < nVertices; ++i)
{
getline(m_mshFile, line);
stringstream st(line);
double x = 0, y = 0, z = 0;
st >> id >> x >> y >> z;
if ((x * x) > 0.000001 && m_mesh->m_spaceDim < 1)
{
m_mesh->m_spaceDim = 1;
}
if ((y * y) > 0.000001 && m_mesh->m_spaceDim < 2)
{
m_mesh->m_spaceDim = 2;
}
if ((z * z) > 0.000001 && m_mesh->m_spaceDim < 3)
{
m_mesh->m_spaceDim = 3;
}
id -= 1; // counter starts at 0
if (id-prevId != 1)
{
cerr << "Gmsh vertex ids should be contiguous" << endl;
abort();
}
prevId = id;
m_mesh->m_node.push_back(boost::shared_ptr<Node>(new Node(id, x, y, z)));
}
}
// Process elements
else if (word == "$Elements")
{
getline(m_mshFile, line);
stringstream s(line);
s >> nEntities;
for (int i = 0; i < nEntities; ++i)
{
getline(m_mshFile, line);
stringstream st(line);
int id = 0, num_tag = 0, num_nodes = 0;
st >> id >> elm_type >> num_tag;
id -= 1; // counter starts at 0
it = elmMap.find(elm_type);
if (it == elmMap.end())
{
cerr << "Error: element type " << elm_type
<< " not supported" << endl;
abort();
}
// Read element tags
vector<int> tags;
for (int j = 0; j < num_tag; ++j)
{
int tag = 0;
st >> tag;
tags.push_back(tag);
}
tags.resize(1);
maxTagId = max(maxTagId, tags[0]);
// Read element node list
vector<NodeSharedPtr> nodeList;
num_nodes = GetNnodes(elm_type);
for (int k = 0; k < num_nodes; ++k)
{
int node = 0;
st >> node;
node -= 1; // counter starts at 0
nodeList.push_back(m_mesh->m_node[node]);
}
// Look up reordering.
oIt = orderingMap.find(elm_type);
// If it's not created, then create it.
if (oIt == orderingMap.end())
{
oIt = orderingMap.insert(
make_pair(elm_type, CreateReordering(elm_type)))
.first;
}
// Apply reordering map where necessary.
if (oIt->second.size() > 0)
{
vector<int> &mapping = oIt->second;
vector<NodeSharedPtr> tmp = nodeList;
for (int i = 0; i < mapping.size(); ++i)
{
nodeList[i] = tmp[mapping[i]];
}
}
// Create element
CreateInstance(it->second.m_e,it->second,nodeList,tags);
// Determine mesh expansion dimension
if (E->GetDim() > m_mesh->m_expDim) {
m_mesh->m_expDim = E->GetDim();
}
m_mesh->m_element[E->GetDim()].push_back(E);
}
}
}
m_mshFile.close();
// Go through element and remap tags if necessary.
map<int, map<LibUtilities::ShapeType, int> > compMap;
map<int, map<LibUtilities::ShapeType, int> >::iterator cIt;
for (int i = 0; i < m_mesh->m_element[m_mesh->m_expDim].size(); ++i)
{
ElementSharedPtr el = m_mesh->m_element[m_mesh->m_expDim][i];
LibUtilities::ShapeType type = el->GetConf().m_e;
vector<int> tags = el->GetTagList();
int tag = tags[0];
cIt = compMap.find(tag);
if (cIt == compMap.end())
{
compMap[tag][type] = tag;
continue;
}
// Reset tag for this element.
sIt = cIt->second.find(type);
if (sIt == cIt->second.end())
{
maxTagId++;
cIt->second[type] = maxTagId;
tags[0] = maxTagId;
el->SetTagList(tags);
}
else if (sIt->second != tag)
{
tags[0] = sIt->second;
el->SetTagList(tags);
}
}
bool printInfo = false;
for (cIt = compMap.begin(); cIt != compMap.end(); ++cIt)
{
if (cIt->second.size() > 1)
{
printInfo = true;
break;
}
}
if (printInfo)
{
cout << "Multiple elements in composite detected; remapped:"
<< endl;
for (cIt = compMap.begin(); cIt != compMap.end(); ++cIt)
{
if (cIt->second.size() > 1)
{
sIt = cIt->second.begin();
cout << "- Tag " << cIt->first << " => " << sIt->second
<< " ("
<< LibUtilities::ShapeTypeMap[sIt->first] << ")";
sIt++;
for (; sIt != cIt->second.end(); ++sIt)
{
cout << ", " << sIt->second << " ("
<< ")";
}
cout << endl;
}
}
}
// Process rest of mesh.
}
vector< int > Nektar::Utilities::InputGmsh::QuadReordering ( ElmtConfig  conf)
private

Create a reordering for quadrilaterals.

Definition at line 570 of file InputGmsh.cpp.

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

Referenced by CreateReordering().

{
const int order = conf.m_order;
const int n = order-1;
// Copy vertices.
vector<int> mapping(4);
for (int i = 0; i < 4; ++i)
{
mapping[i] = i;
}
if (order == 1)
{
return mapping;
}
// Curvilinear edges.
mapping.resize(4 + 4*n);
for (int i = 4; i < 4+4*n; ++i)
{
mapping[i] = i;
}
if (!conf.m_faceNodes)
{
return mapping;
}
// Interior nodes.
vector<int> interior(n*n);
for (int i = 0; i < interior.size(); ++i)
{
interior[i] = i + 4+4*n;
}
if (interior.size() > 0)
{
interior = quadTensorNodeOrdering(interior, n);
}
mapping.insert(mapping.end(), interior.begin(), interior.end());
return mapping;
}
vector< int > Nektar::Utilities::InputGmsh::TetReordering ( ElmtConfig  conf)
private

Create a reordering for tetrahedra.

Definition at line 618 of file InputGmsh.cpp.

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

Referenced by CreateReordering().

{
const int order = conf.m_order;
const int n = order-1;
const int n2 = n*(n-1)/2;
int i, j;
vector<int> mapping(4);
// Copy vertices.
for (i = 0; i < 4; ++i)
{
mapping[i] = i;
}
if (order == 1)
{
return mapping;
}
// Curvilinear edges.
mapping.resize(4 + 6*n);
// Curvilinear edges.
static int gmshToNekEdge[6] = {0,1,2,3,5,4};
static int gmshToNekRev [6] = {0,0,1,1,1,1};
// Reorder edges.
int offset, cnt = 4;
for (i = 0; i < 6; ++i)
{
offset = 4 + n * gmshToNekEdge[i];
if (gmshToNekRev[i])
{
for (int j = 0; j < n; ++j)
{
mapping[offset+n-j-1] = cnt++;
}
}
else
{
for (int j = 0; j < n; ++j)
{
mapping[offset+j] = cnt++;
}
}
}
if (conf.m_faceNodes == false || n2 == 0)
{
return mapping;
}
// Curvilinear faces.
mapping.resize(4 + 6*n + 4*n2);
static int gmshToNekFace[4] = {0,1,3,2};
vector<int> triVertId(3);
triVertId[0] = 0; triVertId[1] = 1; triVertId[2] = 2;
// Loop over Gmsh faces
for (i = 0; i < 4; ++i)
{
int face = gmshToNekFace[i];
int offset2 = 4 + 6*n + i *n2;
offset = 4 + 6*n + face*n2;
// Create a list of interior face nodes for this face only.
vector<int> faceNodes(n2);
vector<int> toAlign (3);
for (j = 0; j < n2; ++j)
{
faceNodes[j] = offset2 + j;
}
// Now get the reordering of this face, which puts Gmsh
// recursive ordering into Nektar++ row-by-row order.
vector<int> tmp = triTensorNodeOrdering(faceNodes, n-1);
HOTriangle<int> hoTri(triVertId, tmp);
// Apply reorientation
if (i == 0 || i == 2)
{
// Triangle verts {0,2,1} --> {0,1,2}
toAlign[0] = 0; toAlign[1] = 2; toAlign[2] = 1;
hoTri.Align(toAlign);
}
else if (i == 3)
{
// Triangle verts {1,2,0} --> {0,1,2}
toAlign[0] = 1; toAlign[1] = 2; toAlign[2] = 0;
hoTri.Align(toAlign);
}
// Fill in mapping.
for (j = 0; j < n2; ++j)
{
mapping[offset+j] = hoTri.surfVerts[j];
}
}
return mapping;
}
vector< int > Nektar::Utilities::InputGmsh::TriReordering ( ElmtConfig  conf)
private

Create a reordering for triangles.

Definition at line 521 of file InputGmsh.cpp.

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

Referenced by CreateReordering().

{
const int order = conf.m_order;
const int n = order-1;
// Copy vertices.
vector<int> mapping(3);
for (int i = 0; i < 3; ++i)
{
mapping[i] = i;
}
if (order == 1)
{
return mapping;
}
// Curvilinear edges.
mapping.resize(3 + 3*n);
for (int i = 3; i < 3+3*n; ++i)
{
mapping[i] = i;
}
if (!conf.m_faceNodes)
{
return mapping;
}
// Interior nodes.
vector<int> interior(n*(n-1)/2);
for (int i = 0; i < interior.size(); ++i)
{
interior[i] = i + 3+3*n;
}
if (interior.size() > 0)
{
interior = triTensorNodeOrdering(interior, n-1);
}
mapping.insert(mapping.end(), interior.begin(), interior.end());
return mapping;
}

Member Data Documentation

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

ModuleKey for class.

Definition at line 60 of file InputGmsh.h.

std::map< unsigned int, ElmtConfig > Nektar::Utilities::InputGmsh::elmMap
static
Initial value:

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

Definition at line 66 of file InputGmsh.h.

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