Nektar++
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. More...
 
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. More...
 
- 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. More...
 
void PrintConfig ()
 Print out all configuration options for a module. More...
 
void SetDefaults ()
 Sets default configuration options for those which have not been set. More...
 
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. More...
 

Static Public Member Functions

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

Static Public Attributes

static ModuleKey className
 ModuleKey for class. More...
 
static std::map< unsigned int, ElmtConfigelmMap
 

Private Member Functions

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

Additional Inherited Members

- Protected Member Functions inherited from Nektar::Utilities::InputModule
void PrintSummary ()
 Print summary of elements. More...
 
void PrintSummary ()
 Print summary of elements. More...
 
- Protected Member Functions inherited from Nektar::Utilities::Module
 Module ()
 
virtual void ProcessEdges (bool ReprocessEdges=true)
 Extract element edges. More...
 
virtual void ProcessFaces (bool ReprocessFaces=true)
 Extract element faces. More...
 
virtual void ProcessElements ()
 Generate element IDs. More...
 
virtual void ProcessComposites ()
 Generate composites. More...
 
void ReorderPrisms (PerMap &perFaces)
 Reorder node IDs so that prisms and tetrahedra are aligned correctly. More...
 
void PrismLines (int prism, PerMap &perFaces, set< int > &prismsDone, vector< ElementSharedPtr > &line)
 
- Protected Attributes inherited from Nektar::Utilities::InputModule
set< string > m_allowedFiles
 
std::ifstream m_mshFile
 Input stream. More...
 
- Protected Attributes inherited from Nektar::Utilities::Module
FieldSharedPtr m_f
 Field object. More...
 
map< string, ConfigOptionm_config
 List of configuration values. More...
 
bool m_requireEquiSpaced
 
MeshSharedPtr m_mesh
 Mesh object. More...
 

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.

162  : InputModule(m)
163  {
164 
165  }
Nektar::Utilities::InputGmsh::~InputGmsh ( )
virtual

Definition at line 167 of file InputGmsh.cpp.

168  {
169 
170  }

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.

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

56  {
58  }
static boost::shared_ptr< DataType > AllocateSharedPtr()
Allocate a shared pointer from the memory pool.
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().

479  {
481 
482  it = elmMap.find(InputGmshEntity);
483 
484  if (it == elmMap.end())
485  {
486  cerr << "Unknown element type " << InputGmshEntity << endl;
487  abort();
488  }
489 
490  // For specific elements, call the appropriate function to perform
491  // the renumbering.
492  switch(it->second.m_e)
493  {
495  return TriReordering(it->second);
496  break;
498  return QuadReordering(it->second);
499  break;
501  return TetReordering(it->second);
502  break;
504  return PrismReordering(it->second);
505  break;
507  return HexReordering(it->second);
508  break;
509  default:
510  break;
511  }
512 
513  // Default: no reordering.
514  vector<int> returnVal;
515  return returnVal;
516  }
vector< int > HexReordering(ElmtConfig conf)
Create a reordering for hexahedra.
Definition: InputGmsh.cpp:807
vector< int > TriReordering(ElmtConfig conf)
Create a reordering for triangles.
Definition: InputGmsh.cpp:521
vector< int > QuadReordering(ElmtConfig conf)
Create a reordering for quadrilaterals.
Definition: InputGmsh.cpp:570
vector< int > PrismReordering(ElmtConfig conf)
Create a reordering for prisms.
Definition: InputGmsh.cpp:732
StandardMatrixTag boost::call_traits< LhsDataType >::const_reference rhs typedef NekMatrix< LhsDataType, StandardMatrixTag >::iterator iterator
vector< int > TetReordering(ElmtConfig conf)
Create a reordering for tetrahedra.
Definition: InputGmsh.cpp:618
static std::map< unsigned int, ElmtConfig > elmMap
Definition: InputGmsh.h:66
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.

958  {
959  using namespace LibUtilities;
960  std::map<unsigned int, ElmtConfig> tmp;
961 
962  // Elmt type, order, face, volume
963  tmp[ 1] = ElmtConfig(eSegment, 1, true, true);
964  tmp[ 2] = ElmtConfig(eTriangle, 1, true, true);
965  tmp[ 3] = ElmtConfig(eQuadrilateral, 1, true, true);
966  tmp[ 4] = ElmtConfig(eTetrahedron, 1, true, true);
967  tmp[ 5] = ElmtConfig(eHexahedron, 1, true, true);
968  tmp[ 6] = ElmtConfig(ePrism, 1, true, true);
969  tmp[ 7] = ElmtConfig(ePyramid, 1, true, true);
970  tmp[ 8] = ElmtConfig(eSegment, 2, true, true);
971  tmp[ 9] = ElmtConfig(eTriangle, 2, true, true);
972  tmp[ 10] = ElmtConfig(eQuadrilateral, 2, true, true);
973  tmp[ 11] = ElmtConfig(eTetrahedron, 2, true, true);
974  tmp[ 12] = ElmtConfig(eHexahedron, 2, true, true);
975  tmp[ 13] = ElmtConfig(ePrism, 2, true, true);
976  tmp[ 14] = ElmtConfig(ePyramid, 2, true, true);
977  tmp[ 15] = ElmtConfig(ePoint, 1, true, false);
978  tmp[ 16] = ElmtConfig(eQuadrilateral, 2, false, false);
979  tmp[ 17] = ElmtConfig(eHexahedron, 2, false, false);
980  tmp[ 18] = ElmtConfig(ePrism, 2, false, false);
981  tmp[ 19] = ElmtConfig(ePyramid, 2, false, false);
982  tmp[ 20] = ElmtConfig(eTriangle, 3, false, false);
983  tmp[ 21] = ElmtConfig(eTriangle, 3, true, false);
984  tmp[ 22] = ElmtConfig(eTriangle, 4, false, false);
985  tmp[ 23] = ElmtConfig(eTriangle, 4, true, false);
986  tmp[ 24] = ElmtConfig(eTriangle, 5, false, false);
987  tmp[ 25] = ElmtConfig(eTriangle, 5, true, false);
988  tmp[ 26] = ElmtConfig(eSegment, 3, true, false);
989  tmp[ 27] = ElmtConfig(eSegment, 4, true, false);
990  tmp[ 28] = ElmtConfig(eSegment, 5, true, false);
991  tmp[ 29] = ElmtConfig(eTetrahedron, 3, true, true);
992  tmp[ 30] = ElmtConfig(eTetrahedron, 4, true, true);
993  tmp[ 31] = ElmtConfig(eTetrahedron, 5, true, true);
994  tmp[ 32] = ElmtConfig(eTetrahedron, 4, true, false);
995  tmp[ 33] = ElmtConfig(eTetrahedron, 5, true, false);
996  tmp[ 36] = ElmtConfig(eQuadrilateral, 3, true, false);
997  tmp[ 37] = ElmtConfig(eQuadrilateral, 4, true, false);
998  tmp[ 38] = ElmtConfig(eQuadrilateral, 5, true, false);
999  tmp[ 39] = ElmtConfig(eQuadrilateral, 3, false, false);
1000  tmp[ 40] = ElmtConfig(eQuadrilateral, 4, false, false);
1001  tmp[ 41] = ElmtConfig(eQuadrilateral, 5, false, false);
1002  tmp[ 42] = ElmtConfig(eTriangle, 6, true, false);
1003  tmp[ 43] = ElmtConfig(eTriangle, 7, true, false);
1004  tmp[ 44] = ElmtConfig(eTriangle, 8, true, false);
1005  tmp[ 45] = ElmtConfig(eTriangle, 9, true, false);
1006  tmp[ 46] = ElmtConfig(eTriangle, 10, true, false);
1007  tmp[ 47] = ElmtConfig(eQuadrilateral, 6, true, false);
1008  tmp[ 48] = ElmtConfig(eQuadrilateral, 7, true, false);
1009  tmp[ 49] = ElmtConfig(eQuadrilateral, 8, true, false);
1010  tmp[ 50] = ElmtConfig(eQuadrilateral, 9, true, false);
1011  tmp[ 51] = ElmtConfig(eQuadrilateral, 10, true, false);
1012  tmp[ 52] = ElmtConfig(eTriangle, 6, false, false);
1013  tmp[ 53] = ElmtConfig(eTriangle, 7, false, false);
1014  tmp[ 54] = ElmtConfig(eTriangle, 8, false, false);
1015  tmp[ 55] = ElmtConfig(eTriangle, 9, false, false);
1016  tmp[ 56] = ElmtConfig(eTriangle, 10, false, false);
1017  tmp[ 57] = ElmtConfig(eQuadrilateral, 6, false, false);
1018  tmp[ 58] = ElmtConfig(eQuadrilateral, 7, false, false);
1019  tmp[ 59] = ElmtConfig(eQuadrilateral, 8, false, false);
1020  tmp[ 60] = ElmtConfig(eQuadrilateral, 9, false, false);
1021  tmp[ 61] = ElmtConfig(eQuadrilateral, 10, false, false);
1022  tmp[ 62] = ElmtConfig(eSegment, 6, true, false);
1023  tmp[ 63] = ElmtConfig(eSegment, 7, true, false);
1024  tmp[ 64] = ElmtConfig(eSegment, 8, true, false);
1025  tmp[ 65] = ElmtConfig(eSegment, 9, true, false);
1026  tmp[ 66] = ElmtConfig(eSegment, 10, true, false);
1027  tmp[ 71] = ElmtConfig(eTetrahedron, 6, true, true);
1028  tmp[ 72] = ElmtConfig(eTetrahedron, 7, true, true);
1029  tmp[ 73] = ElmtConfig(eTetrahedron, 8, true, true);
1030  tmp[ 74] = ElmtConfig(eTetrahedron, 9, true, true);
1031  tmp[ 75] = ElmtConfig(eTetrahedron, 10, true, true);
1032  tmp[ 79] = ElmtConfig(eTetrahedron, 6, true, false);
1033  tmp[ 80] = ElmtConfig(eTetrahedron, 7, true, false);
1034  tmp[ 81] = ElmtConfig(eTetrahedron, 8, true, false);
1035  tmp[ 82] = ElmtConfig(eTetrahedron, 9, true, false);
1036  tmp[ 83] = ElmtConfig(eTetrahedron, 10, true, false);
1037  tmp[ 90] = ElmtConfig(ePrism, 3, true, true);
1038  tmp[ 91] = ElmtConfig(ePrism, 4, true, true);
1039  tmp[ 92] = ElmtConfig(eHexahedron, 3, true, true);
1040  tmp[ 93] = ElmtConfig(eHexahedron, 4, true, true);
1041  tmp[ 94] = ElmtConfig(eHexahedron, 5, true, true);
1042  tmp[ 95] = ElmtConfig(eHexahedron, 6, true, true);
1043  tmp[ 96] = ElmtConfig(eHexahedron, 7, true, true);
1044  tmp[ 97] = ElmtConfig(eHexahedron, 8, true, true);
1045  tmp[ 98] = ElmtConfig(eHexahedron, 9, true, true);
1046  tmp[ 99] = ElmtConfig(eHexahedron, 3, true, false);
1047  tmp[100] = ElmtConfig(eHexahedron, 4, true, false);
1048  tmp[101] = ElmtConfig(eHexahedron, 5, true, false);
1049  tmp[102] = ElmtConfig(eHexahedron, 6, true, false);
1050  tmp[103] = ElmtConfig(eHexahedron, 7, true, false);
1051  tmp[104] = ElmtConfig(eHexahedron, 8, true, false);
1052  tmp[105] = ElmtConfig(eHexahedron, 9, true, false);
1053  tmp[106] = ElmtConfig(ePrism, 5, true, true);
1054  tmp[107] = ElmtConfig(ePrism, 6, true, true);
1055  tmp[108] = ElmtConfig(ePrism, 7, true, true);
1056  tmp[109] = ElmtConfig(ePrism, 8, true, true);
1057  tmp[110] = ElmtConfig(ePrism, 9, true, true);
1058  tmp[111] = ElmtConfig(ePrism, 3, true, false);
1059  tmp[112] = ElmtConfig(ePrism, 4, true, false);
1060  tmp[113] = ElmtConfig(ePrism, 5, true, false);
1061  tmp[114] = ElmtConfig(ePrism, 6, true, false);
1062  tmp[115] = ElmtConfig(ePrism, 7, true, false);
1063  tmp[116] = ElmtConfig(ePrism, 8, true, false);
1064  tmp[117] = ElmtConfig(ePrism, 9, true, false);
1065  tmp[118] = ElmtConfig(ePyramid, 3, true, true);
1066  tmp[119] = ElmtConfig(ePyramid, 4, true, true);
1067  tmp[120] = ElmtConfig(ePyramid, 5, true, true);
1068  tmp[121] = ElmtConfig(ePyramid, 6, true, true);
1069  tmp[122] = ElmtConfig(ePyramid, 7, true, true);
1070  tmp[123] = ElmtConfig(ePyramid, 8, true, true);
1071  tmp[124] = ElmtConfig(ePyramid, 9, true, true);
1072  tmp[125] = ElmtConfig(ePyramid, 3, true, false);
1073  tmp[126] = ElmtConfig(ePyramid, 4, true, false);
1074  tmp[127] = ElmtConfig(ePyramid, 5, true, false);
1075  tmp[128] = ElmtConfig(ePyramid, 6, true, false);
1076  tmp[129] = ElmtConfig(ePyramid, 7, true, false);
1077  tmp[130] = ElmtConfig(ePyramid, 7, true, false);
1078  tmp[131] = ElmtConfig(ePyramid, 8, true, false);
1079 
1080  return tmp;
1081  }
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().

421  {
422  int nNodes;
424 
425  it = elmMap.find(InputGmshEntity);
426 
427  if (it == elmMap.end())
428  {
429  cerr << "Unknown element type " << InputGmshEntity << endl;
430  abort();
431  }
432 
433  switch(it->second.m_e)
434  {
436  nNodes = Point:: GetNumNodes(it->second);
437  break;
439  nNodes = Line:: GetNumNodes(it->second);
440  break;
442  nNodes = Triangle:: GetNumNodes(it->second);
443  break;
445  nNodes = Quadrilateral::GetNumNodes(it->second);
446  break;
448  nNodes = Tetrahedron:: GetNumNodes(it->second);
449  it->second.m_faceCurveType =
451  break;
453  nNodes = Pyramid:: GetNumNodes(it->second);
454  break;
456  nNodes = Prism:: GetNumNodes(it->second);
457  break;
459  nNodes = Hexahedron:: GetNumNodes(it->second);
460  break;
461  default:
462  cerr << "Unknown element type!" << endl;
463  abort();
464  break;
465  }
466 
467  return nNodes;
468  }
static unsigned int GetNumNodes(ElmtConfig pConf)
Return the number of nodes defining a prism.
static unsigned int GetNumNodes(ElmtConfig pConf)
Return the number of nodes defining a line.
static unsigned int GetNumNodes(ElmtConfig pConf)
Return the number of nodes defining a pyramid.
static unsigned int GetNumNodes(ElmtConfig pConf)
Return the number of nodes defining a hexahedron.
static unsigned int GetNumNodes(ElmtConfig pConf)
Return the number of nodes defining a point (i.e. return 1).
static unsigned int GetNumNodes(ElmtConfig pConf)
Return the number of nodes defining a tetrahedron.
StandardMatrixTag boost::call_traits< LhsDataType >::const_reference rhs typedef NekMatrix< LhsDataType, StandardMatrixTag >::iterator iterator
2D Evenly-spaced points on a Triangle
Definition: PointsType.h:70
static unsigned int GetNumNodes(ElmtConfig pConf)
Return the number of nodes defining a triangle.
static unsigned int GetNumNodes(ElmtConfig pConf)
Return the number of nodes defining a quadrilateral.
static std::map< unsigned int, ElmtConfig > elmMap
Definition: InputGmsh.h:66
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().

808  {
809  const int order = conf.m_order;
810  const int n = order-1;
811  const int n2 = n * n;
812  int i, j, k;
813 
814  vector<int> mapping;
815 
816  // Map taking Gmsh edges to Nektar++ edges.
817  static int gmshToNekEdge[12] = {
818  0, -3, 4, 1, 5, 2, 6, 7, 8, -11, 9, 10
819  };
820 
821  // Push back vertices.
822  mapping.resize(8);
823  for (i = 0; i < 8; ++i)
824  {
825  mapping[i] = i;
826  }
827 
828  if (order == 1)
829  {
830  return mapping;
831  }
832 
833  // Curvilinear edges
834  mapping.resize(8 + 12*n);
835 
836  // Reorder edges.
837  int cnt = 8, offset;
838  for (i = 0; i < 12; ++i)
839  {
840  int edge = gmshToNekEdge[i];
841  offset = 8 + n * abs(edge);
842 
843  if (edge < 0)
844  {
845  for (int j = 0; j < n; ++j)
846  {
847  mapping[offset+n-j-1] = cnt++;
848  }
849  }
850  else
851  {
852  for (int j = 0; j < n; ++j)
853  {
854  mapping[offset+j] = cnt++;
855  }
856  }
857  }
858 
859  if (conf.m_faceNodes == false || n2 == 0)
860  {
861  return mapping;
862  }
863 
864  // Curvilinear face nodes.
865  mapping.resize(8 + 12*n + 6*n2);
866 
867  // Map which takes Gmsh -> Nektar++ faces in the local element.
868  static int gmsh2NekFace[6] = {0,1,4,2,3,5};
869 
870  // Map which defines orientation between Gmsh and Nektar++ faces.
871  StdRegions::Orientation faceOrient[6] = {
877  StdRegions::eDir1FwdDir1_Dir2FwdDir2
878  };
879 
880  for (i = 0; i < 6; ++i)
881  {
882  int face = gmsh2NekFace[i];
883  int offset2 = 8 + 12 * n + i * n2;
884  offset = 8 + 12 * n + face * n2;
885 
886  // Create a list of interior face nodes for this face only.
887  vector<int> faceNodes(n2);
888  for (j = 0; j < n2; ++j)
889  {
890  faceNodes[j] = offset2 + j;
891  }
892 
893  // Now get the reordering of this face, which puts Gmsh
894  // recursive ordering into Nektar++ row-by-row order.
895  vector<int> tmp = quadTensorNodeOrdering(faceNodes, n);
896 
897  // Finally reorient the face according to the geometry
898  // differences.
899  if (faceOrient[i] == StdRegions::eDir1FwdDir1_Dir2FwdDir2)
900  {
901  // Orientation is the same, just copy.
902  for (j = 0; j < n2; ++j)
903  {
904  mapping[offset+j] = tmp[j];
905  }
906  }
907  else if (faceOrient[i] == StdRegions::eDir1FwdDir2_Dir2FwdDir1)
908  {
909  // Tranposed faces
910  for (j = 0; j < n; ++j)
911  {
912  for (k = 0; k < n; ++k)
913  {
914  mapping[offset + j*n + k] = tmp[k*n + j];
915  }
916  }
917  }
918  else if (faceOrient[i] == StdRegions::eDir1BwdDir1_Dir2FwdDir2)
919  {
920  for (j = 0; j < n; ++j)
921  {
922  for (k = 0; k < n; ++k)
923  {
924  mapping[offset + j*n + k] = tmp[j*n + (n-k-1)];
925  }
926  }
927  }
928  }
929 
930  if (conf.m_volumeNodes == false)
931  {
932  return mapping;
933  }
934 
935  const int totPoints = (order+1) * (order+1) * (order+1);
936  mapping.resize(totPoints);
937 
938  // TODO: Fix ordering of volume nodes.
939  for (i = 8 + 12*n + 6*n2; i < totPoints; ++i)
940  {
941  mapping[i] = i;
942  }
943 
944  return mapping;
945  }
std::vector< int > quadTensorNodeOrdering(const std::vector< int > &nodes, int n)
Reorder a quadrilateral to appear in Nektar++ ordering from Gmsh.
Definition: InputGmsh.cpp:59
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().

733  {
734  const int order = conf.m_order;
735  const int n = order-1;
736 
737  int i;
738  vector<int> mapping(6);
739 
740  // To get from Gmsh -> Nektar++ prism, coordinates axes are
741  // different; need to mirror in the triangular faces, and then
742  // reorder vertices to make ordering anticlockwise on base quad.
743  static int gmshToNekVerts[6] = {3,4,1,0,5,2};
744 
745  for (i = 0; i < 6; ++i)
746  {
747  mapping[i] = gmshToNekVerts[i];
748  }
749 
750  if (order == 1)
751  {
752  return mapping;
753  }
754 
755  // Curvilinear edges.
756  mapping.resize(6 + 9*n);
757 
758  static int gmshToNekEdge[9] = {2,7,3,6,1,8,0,4,5};
759  static int gmshToNekRev [9] = {1,0,1,0,1,1,0,0,0};
760 
761  // Reorder edges.
762  int offset, cnt = 6;
763  for (i = 0; i < 9; ++i)
764  {
765  offset = 6 + n * gmshToNekEdge[i];
766 
767  if (gmshToNekRev[i])
768  {
769  for (int j = 0; j < n; ++j)
770  {
771  mapping[offset+n-j-1] = cnt++;
772  }
773  }
774  else
775  {
776  for (int j = 0; j < n; ++j)
777  {
778  mapping[offset+j] = cnt++;
779  }
780  }
781  }
782 
783  if (conf.m_faceNodes == false)
784  {
785  return mapping;
786  }
787 
788  if (order > 2)
789  {
790  cerr << "Gmsh prisms of order > 2 with face curvature "
791  << "not supported in MeshConvert (or indeed Gmsh at"
792  << "time of writing)." << endl;
793  abort();
794  }
795 
796  mapping.resize(18);
797  mapping[15] = 15;
798  mapping[16] = 17;
799  mapping[17] = 16;
800 
801  return mapping;
802  }
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.

183  {
184  // Open the file stream.
185  OpenStream();
186 
187  m_mesh->m_expDim = 0;
188  m_mesh->m_spaceDim = 0;
189  string line;
190  int nVertices = 0;
191  int nEntities = 0;
192  int elm_type = 0;
193  int prevId = -1;
194  int maxTagId = -1;
195 
197 
198  // This map takes each element ID and maps it to a permutation map
199  // that is required to take Gmsh element node orderings and map them
200  // to Nektar++ orderings.
201  boost::unordered_map<int, vector<int> > orderingMap;
202  boost::unordered_map<int, vector<int> >::iterator oIt;
203 
204  if (m_mesh->m_verbose)
205  {
206  cout << "InputGmsh: Start reading file..." << endl;
207  }
208 
209  while (!m_mshFile.eof())
210  {
211  getline(m_mshFile, line);
212  stringstream s(line);
213  string word;
214  s >> word;
215 
216  // Process nodes.
217  if (word == "$Nodes")
218  {
219  getline(m_mshFile, line);
220  stringstream s(line);
221  s >> nVertices;
222  int id = 0;
223  for (int i = 0; i < nVertices; ++i)
224  {
225  getline(m_mshFile, line);
226  stringstream st(line);
227  double x = 0, y = 0, z = 0;
228  st >> id >> x >> y >> z;
229 
230  if ((x * x) > 0.000001 && m_mesh->m_spaceDim < 1)
231  {
232  m_mesh->m_spaceDim = 1;
233  }
234  if ((y * y) > 0.000001 && m_mesh->m_spaceDim < 2)
235  {
236  m_mesh->m_spaceDim = 2;
237  }
238  if ((z * z) > 0.000001 && m_mesh->m_spaceDim < 3)
239  {
240  m_mesh->m_spaceDim = 3;
241  }
242 
243  id -= 1; // counter starts at 0
244 
245  if (id-prevId != 1)
246  {
247  cerr << "Gmsh vertex ids should be contiguous" << endl;
248  abort();
249  }
250  prevId = id;
251  m_mesh->m_node.push_back(boost::shared_ptr<Node>(new Node(id, x, y, z)));
252  }
253  }
254  // Process elements
255  else if (word == "$Elements")
256  {
257  getline(m_mshFile, line);
258  stringstream s(line);
259  s >> nEntities;
260  for (int i = 0; i < nEntities; ++i)
261  {
262  getline(m_mshFile, line);
263  stringstream st(line);
264  int id = 0, num_tag = 0, num_nodes = 0;
265 
266  st >> id >> elm_type >> num_tag;
267  id -= 1; // counter starts at 0
268 
269  it = elmMap.find(elm_type);
270  if (it == elmMap.end())
271  {
272  cerr << "Error: element type " << elm_type
273  << " not supported" << endl;
274  abort();
275  }
276 
277  // Read element tags
278  vector<int> tags;
279  for (int j = 0; j < num_tag; ++j)
280  {
281  int tag = 0;
282  st >> tag;
283  tags.push_back(tag);
284  }
285  tags.resize(1);
286 
287  maxTagId = max(maxTagId, tags[0]);
288 
289  // Read element node list
290  vector<NodeSharedPtr> nodeList;
291  num_nodes = GetNnodes(elm_type);
292  for (int k = 0; k < num_nodes; ++k)
293  {
294  int node = 0;
295  st >> node;
296  node -= 1; // counter starts at 0
297  nodeList.push_back(m_mesh->m_node[node]);
298  }
299 
300  // Look up reordering.
301  oIt = orderingMap.find(elm_type);
302 
303  // If it's not created, then create it.
304  if (oIt == orderingMap.end())
305  {
306  oIt = orderingMap.insert(
307  make_pair(elm_type, CreateReordering(elm_type)))
308  .first;
309  }
310 
311  // Apply reordering map where necessary.
312  if (oIt->second.size() > 0)
313  {
314  vector<int> &mapping = oIt->second;
315  vector<NodeSharedPtr> tmp = nodeList;
316  for (int i = 0; i < mapping.size(); ++i)
317  {
318  nodeList[i] = tmp[mapping[i]];
319  }
320  }
321 
322  // Create element
324  CreateInstance(it->second.m_e,it->second,nodeList,tags);
325 
326  // Determine mesh expansion dimension
327  if (E->GetDim() > m_mesh->m_expDim) {
328  m_mesh->m_expDim = E->GetDim();
329  }
330  m_mesh->m_element[E->GetDim()].push_back(E);
331  }
332  }
333  }
334  m_mshFile.close();
335 
336  // Go through element and remap tags if necessary.
337  map<int, map<LibUtilities::ShapeType, int> > compMap;
338  map<int, map<LibUtilities::ShapeType, int> >::iterator cIt;
340 
341  for (int i = 0; i < m_mesh->m_element[m_mesh->m_expDim].size(); ++i)
342  {
343  ElementSharedPtr el = m_mesh->m_element[m_mesh->m_expDim][i];
344  LibUtilities::ShapeType type = el->GetConf().m_e;
345 
346  vector<int> tags = el->GetTagList();
347  int tag = tags[0];
348 
349  cIt = compMap.find(tag);
350 
351  if (cIt == compMap.end())
352  {
353  compMap[tag][type] = tag;
354  continue;
355  }
356 
357  // Reset tag for this element.
358  sIt = cIt->second.find(type);
359  if (sIt == cIt->second.end())
360  {
361  maxTagId++;
362  cIt->second[type] = maxTagId;
363  tags[0] = maxTagId;
364  el->SetTagList(tags);
365  }
366  else if (sIt->second != tag)
367  {
368  tags[0] = sIt->second;
369  el->SetTagList(tags);
370  }
371  }
372 
373  bool printInfo = false;
374  for (cIt = compMap.begin(); cIt != compMap.end(); ++cIt)
375  {
376  if (cIt->second.size() > 1)
377  {
378  printInfo = true;
379  break;
380  }
381  }
382 
383  if (printInfo)
384  {
385  cout << "Multiple elements in composite detected; remapped:"
386  << endl;
387  for (cIt = compMap.begin(); cIt != compMap.end(); ++cIt)
388  {
389  if (cIt->second.size() > 1)
390  {
391  sIt = cIt->second.begin();
392  cout << "- Tag " << cIt->first << " => " << sIt->second
393  << " ("
394  << LibUtilities::ShapeTypeMap[sIt->first] << ")";
395  sIt++;
396 
397  for (; sIt != cIt->second.end(); ++sIt)
398  {
399  cout << ", " << sIt->second << " ("
400  << LibUtilities::ShapeTypeMap[sIt->first]
401  << ")";
402  }
403 
404  cout << endl;
405  }
406  }
407  }
408 
409  // Process rest of mesh.
410  ProcessVertices ();
411  ProcessEdges ();
412  ProcessFaces ();
413  ProcessElements ();
415  }
std::ifstream m_mshFile
Input stream.
MeshSharedPtr m_mesh
Mesh object.
const char *const ShapeTypeMap[]
Definition: ShapeType.hpp:66
virtual void ProcessEdges(bool ReprocessEdges=true)
Extract element edges.
boost::shared_ptr< Element > ElementSharedPtr
Shared pointer to an element.
Definition: MeshElements.h:63
virtual void ProcessVertices()
Extract element vertices.
vector< int > CreateReordering(unsigned int InputGmshEntity)
Create a reordering map for a given element.
Definition: InputGmsh.cpp:478
virtual void ProcessElements()
Generate element IDs.
virtual void ProcessComposites()
Generate composites.
StandardMatrixTag boost::call_traits< LhsDataType >::const_reference rhs typedef NekMatrix< LhsDataType, StandardMatrixTag >::iterator iterator
int GetNnodes(unsigned int InputGmshEntity)
Definition: InputGmsh.cpp:420
virtual void ProcessFaces(bool ReprocessFaces=true)
Extract element faces.
void OpenStream()
Open a file for input.
ElementFactory & GetElementFactory()
static std::map< unsigned int, ElmtConfig > elmMap
Definition: InputGmsh.h:66
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().

571  {
572  const int order = conf.m_order;
573  const int n = order-1;
574 
575  // Copy vertices.
576  vector<int> mapping(4);
577  for (int i = 0; i < 4; ++i)
578  {
579  mapping[i] = i;
580  }
581 
582  if (order == 1)
583  {
584  return mapping;
585  }
586 
587  // Curvilinear edges.
588  mapping.resize(4 + 4*n);
589 
590  for (int i = 4; i < 4+4*n; ++i)
591  {
592  mapping[i] = i;
593  }
594 
595  if (!conf.m_faceNodes)
596  {
597  return mapping;
598  }
599 
600  // Interior nodes.
601  vector<int> interior(n*n);
602  for (int i = 0; i < interior.size(); ++i)
603  {
604  interior[i] = i + 4+4*n;
605  }
606 
607  if (interior.size() > 0)
608  {
609  interior = quadTensorNodeOrdering(interior, n);
610  }
611  mapping.insert(mapping.end(), interior.begin(), interior.end());
612  return mapping;
613  }
std::vector< int > quadTensorNodeOrdering(const std::vector< int > &nodes, int n)
Reorder a quadrilateral to appear in Nektar++ ordering from Gmsh.
Definition: InputGmsh.cpp:59
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().

619  {
620  const int order = conf.m_order;
621  const int n = order-1;
622  const int n2 = n*(n-1)/2;
623 
624  int i, j;
625  vector<int> mapping(4);
626 
627  // Copy vertices.
628  for (i = 0; i < 4; ++i)
629  {
630  mapping[i] = i;
631  }
632 
633  if (order == 1)
634  {
635  return mapping;
636  }
637 
638  // Curvilinear edges.
639  mapping.resize(4 + 6*n);
640 
641  // Curvilinear edges.
642  static int gmshToNekEdge[6] = {0,1,2,3,5,4};
643  static int gmshToNekRev [6] = {0,0,1,1,1,1};
644 
645  // Reorder edges.
646  int offset, cnt = 4;
647  for (i = 0; i < 6; ++i)
648  {
649  offset = 4 + n * gmshToNekEdge[i];
650 
651  if (gmshToNekRev[i])
652  {
653  for (int j = 0; j < n; ++j)
654  {
655  mapping[offset+n-j-1] = cnt++;
656  }
657  }
658  else
659  {
660  for (int j = 0; j < n; ++j)
661  {
662  mapping[offset+j] = cnt++;
663  }
664  }
665  }
666 
667  if (conf.m_faceNodes == false || n2 == 0)
668  {
669  return mapping;
670  }
671 
672  // Curvilinear faces.
673  mapping.resize(4 + 6*n + 4*n2);
674 
675  static int gmshToNekFace[4] = {0,1,3,2};
676 
677  vector<int> triVertId(3);
678  triVertId[0] = 0; triVertId[1] = 1; triVertId[2] = 2;
679 
680  // Loop over Gmsh faces
681  for (i = 0; i < 4; ++i)
682  {
683  int face = gmshToNekFace[i];
684  int offset2 = 4 + 6*n + i *n2;
685  offset = 4 + 6*n + face*n2;
686 
687  // Create a list of interior face nodes for this face only.
688  vector<int> faceNodes(n2);
689  vector<int> toAlign (3);
690  for (j = 0; j < n2; ++j)
691  {
692  faceNodes[j] = offset2 + j;
693  }
694 
695  // Now get the reordering of this face, which puts Gmsh
696  // recursive ordering into Nektar++ row-by-row order.
697  vector<int> tmp = triTensorNodeOrdering(faceNodes, n-1);
698  HOTriangle<int> hoTri(triVertId, tmp);
699 
700  // Apply reorientation
701  if (i == 0 || i == 2)
702  {
703  // Triangle verts {0,2,1} --> {0,1,2}
704  toAlign[0] = 0; toAlign[1] = 2; toAlign[2] = 1;
705  hoTri.Align(toAlign);
706  }
707  else if (i == 3)
708  {
709  // Triangle verts {1,2,0} --> {0,1,2}
710  toAlign[0] = 1; toAlign[1] = 2; toAlign[2] = 0;
711  hoTri.Align(toAlign);
712  }
713 
714  // Fill in mapping.
715  for (j = 0; j < n2; ++j)
716  {
717  mapping[offset+j] = hoTri.surfVerts[j];
718  }
719  }
720 
721  return mapping;
722  }
std::vector< int > triTensorNodeOrdering(const std::vector< int > &nodes, int n)
Definition: InputGmsh.cpp:107
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().

522  {
523  const int order = conf.m_order;
524  const int n = order-1;
525 
526  // Copy vertices.
527  vector<int> mapping(3);
528  for (int i = 0; i < 3; ++i)
529  {
530  mapping[i] = i;
531  }
532 
533  if (order == 1)
534  {
535  return mapping;
536  }
537 
538  // Curvilinear edges.
539  mapping.resize(3 + 3*n);
540 
541  for (int i = 3; i < 3+3*n; ++i)
542  {
543  mapping[i] = i;
544  }
545 
546  if (!conf.m_faceNodes)
547  {
548  return mapping;
549  }
550 
551  // Interior nodes.
552  vector<int> interior(n*(n-1)/2);
553  for (int i = 0; i < interior.size(); ++i)
554  {
555  interior[i] = i + 3+3*n;
556  }
557 
558  if (interior.size() > 0)
559  {
560  interior = triTensorNodeOrdering(interior, n-1);
561  }
562 
563  mapping.insert(mapping.end(), interior.begin(), interior.end());
564  return mapping;
565  }
std::vector< int > triTensorNodeOrdering(const std::vector< int > &nodes, int n)
Definition: InputGmsh.cpp:107

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().