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

Converter for VTK files. More...

#include <InputStarTec.h>

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

Public Member Functions

 InputTec (NekMeshUtils::MeshSharedPtr m)
 
virtual ~InputTec ()
 
virtual void Process ()
 Populate and validate required data structures. More...
 
void ReadZone (int &nComposite)
 
- 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 Public Attributes

static NekMeshUtils::ModuleKey className
 

Protected Member Functions

void GenElement3D (std::vector< NekMeshUtils::NodeSharedPtr > &Nodes, int i, std::vector< int > &ElementFaces, std::vector< std::vector< int > > &FaceNodes, int ncomposite, bool DoOrient)
 
void GenElement2D (std::vector< NekMeshUtils::NodeSharedPtr > &Nodes, int i, std::vector< int > &ElementFaces, std::vector< std::vector< int > > &FaceNodes, int ncomposite)
 
Array< OneD, int > SortEdgeNodes (std::vector< NekMeshUtils::NodeSharedPtr > &Nodes, std::vector< int > &ElementFaces, std::vector< std::vector< int > > &FaceNodes)
 
Array< OneD, int > SortFaceNodes (std::vector< NekMeshUtils::NodeSharedPtr > &Nodes, std::vector< int > &ElementFaces, std::vector< std::vector< int > > &FaceNodes)
 
void ResetNodes (std::vector< NekMeshUtils::NodeSharedPtr > &Nodes, Array< OneD, std::vector< int > > &ElementFaces, std::vector< std::vector< int > > &FaceNodes)
 
- 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)
 

Additional Inherited Members

- 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 VTK files.

Definition at line 45 of file InputStarTec.h.

Constructor & Destructor Documentation

◆ InputTec()

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

Definition at line 56 of file InputStarTec.cpp.

56  : InputModule(m)
57 {
58 }
NEKMESHUTILS_EXPORT InputModule(MeshSharedPtr p_m)

◆ ~InputTec()

Nektar::Utilities::InputTec::~InputTec ( )
virtual

Definition at line 60 of file InputStarTec.cpp.

61 {
62 }

Member Function Documentation

◆ create()

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

Creates an instance of this class.

Definition at line 49 of file InputStarTec.h.

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

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

◆ GenElement2D()

void Nektar::Utilities::InputTec::GenElement2D ( std::vector< NekMeshUtils::NodeSharedPtr > &  Nodes,
int  i,
std::vector< int > &  ElementFaces,
std::vector< std::vector< int > > &  FaceNodes,
int  ncomposite 
)
protected

Definition at line 670 of file InputStarTec.cpp.

References Nektar::LibUtilities::NekFactory< tKey, tBase, tParam >::CreateInstance(), Nektar::ErrorUtil::efatal, Nektar::LibUtilities::eQuadrilateral, Nektar::LibUtilities::eTriangle, Nektar::NekMeshUtils::GetElementFactory(), Nektar::NekMeshUtils::Module::m_mesh, NEKERROR, and SortEdgeNodes().

Referenced by ReadZone().

675 {
676  boost::ignore_unused(i);
677 
679  // set up Node list
680 
681  if (ElementFaces.size() == 3)
682  {
683  elType = LibUtilities::eTriangle;
684  }
685  else if (ElementFaces.size() == 4)
686  {
688  }
689  else
690  {
692  "Not set up for elements which are not Tris or Quads");
693  }
694 
695  // Create element tags
696  vector<int> tags;
697  tags.push_back(nComposite);
698 
699  // make unique node list
700  vector<NodeSharedPtr> nodeList;
701  Array<OneD, int> Nodes = SortEdgeNodes(VertNodes, ElementFaces, FaceNodes);
702  for (int j = 0; j < Nodes.num_elements(); ++j)
703  {
704  nodeList.push_back(VertNodes[Nodes[j]]);
705  }
706 
707  // Create element
708  ElmtConfig conf(elType, 1, true, true);
709  ElementSharedPtr E =
710  GetElementFactory().CreateInstance(elType, conf, nodeList, tags);
711 
712  m_mesh->m_element[E->GetDim()].push_back(E);
713 }
Basic information about an element.
Definition: ElementConfig.h:49
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mod...
Definition: ErrorUtil.hpp:209
ElementFactory & GetElementFactory()
Definition: Element.cpp:44
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:144
std::shared_ptr< Element > ElementSharedPtr
Definition: Edge.h:49
Array< OneD, int > SortEdgeNodes(std::vector< NekMeshUtils::NodeSharedPtr > &Nodes, std::vector< int > &ElementFaces, std::vector< std::vector< int > > &FaceNodes)

◆ GenElement3D()

void Nektar::Utilities::InputTec::GenElement3D ( std::vector< NekMeshUtils::NodeSharedPtr > &  Nodes,
int  i,
std::vector< int > &  ElementFaces,
std::vector< std::vector< int > > &  FaceNodes,
int  ncomposite,
bool  DoOrient 
)
protected

Definition at line 715 of file InputStarTec.cpp.

References Nektar::LibUtilities::NekFactory< tKey, tBase, tParam >::CreateInstance(), Nektar::ErrorUtil::efatal, Nektar::LibUtilities::ePrism, Nektar::LibUtilities::ePyramid, Nektar::LibUtilities::eTetrahedron, Nektar::NekMeshUtils::GetElementFactory(), Nektar::NekMeshUtils::Module::m_mesh, NEKERROR, and SortFaceNodes().

Referenced by ReadZone().

721 {
722  boost::ignore_unused(i);
723 
725  // set up Node list
726  Array<OneD, int> Nodes = SortFaceNodes(VertNodes, ElementFaces, FaceNodes);
727  int nnodes = Nodes.num_elements();
728  map<LibUtilities::ShapeType, int> domainComposite;
729 
730  // Set Nodes -- Not sure we need this so could
731  // m_mesh->m_node = VertNodes;
732 
733  // element type
734  if (nnodes == 4)
735  {
737  }
738  else if (nnodes == 5)
739  {
740  elType = LibUtilities::ePyramid;
741  }
742  else if (nnodes == 6)
743  {
744  elType = LibUtilities::ePrism;
745  }
746  else
747  {
749  "Not set up for elements which are not Tets, "
750  "Prisms or Pyramids.");
751  }
752 
753  // Create element tags
754  vector<int> tags;
755  tags.push_back(nComposite);
756 
757  // make unique node list
758  vector<NodeSharedPtr> nodeList;
759  for (int j = 0; j < Nodes.num_elements(); ++j)
760  {
761  nodeList.push_back(VertNodes[Nodes[j]]);
762  }
763 
764  // Create element
765  if (elType != LibUtilities::ePyramid)
766  {
767  ElmtConfig conf(elType, 1, true, true, DoOrient);
768  ElementSharedPtr E =
769  GetElementFactory().CreateInstance(elType, conf, nodeList, tags);
770 
771  m_mesh->m_element[E->GetDim()].push_back(E);
772  }
773  else
774  {
775  cout << "Warning: Pyramid detected " << endl;
776  }
777 }
Basic information about an element.
Definition: ElementConfig.h:49
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mod...
Definition: ErrorUtil.hpp:209
ElementFactory & GetElementFactory()
Definition: Element.cpp:44
Array< OneD, int > SortFaceNodes(std::vector< NekMeshUtils::NodeSharedPtr > &Nodes, std::vector< int > &ElementFaces, std::vector< std::vector< int > > &FaceNodes)
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:144
std::shared_ptr< Element > ElementSharedPtr
Definition: Edge.h:49

◆ Process()

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

Populate and validate required data structures.

Tecplot file Polyhedron format contains a list of nodes, a node count per face, the node ids, Element ids that are on the left of each face and Element ids which are on the right of each face. There are then a series of zone of each surface. In the case of a surface the number of nodes is not provided indicating it is a 2D zone

Parameters
pFilenameFilename of Tecplot file to read.

Implements Nektar::NekMeshUtils::Module.

Definition at line 74 of file InputStarTec.cpp.

References Nektar::NekMeshUtils::Module::m_mesh, Nektar::NekMeshUtils::InputModule::m_mshFile, Nektar::NekMeshUtils::InputModule::OpenStream(), Nektar::NekMeshUtils::InputModule::PrintSummary(), Nektar::NekMeshUtils::Module::ProcessComposites(), Nektar::NekMeshUtils::Module::ProcessEdges(), Nektar::NekMeshUtils::Module::ProcessElements(), Nektar::NekMeshUtils::Module::ProcessFaces(), and ReadZone().

75 {
76  m_mesh->m_expDim = 3;
77  m_mesh->m_spaceDim = 3;
78 
79  if (m_mesh->m_verbose)
80  {
81  cout << "InputStarTec: Start reading file..." << endl;
82  }
83 
84  string line, word;
85 
86  // Open the file stream.
87  OpenStream();
88 
89  int nComposite = 0;
90 
91  // read first zone (Hopefully 3D)
92  while (!m_mshFile.eof())
93  {
94  getline(m_mshFile, line);
95  if (line.find("ZONE") != string::npos)
96  {
97  ReadZone(nComposite);
98  break;
99  }
100  }
101 
102  // read remaining 2D zones
103  while (!m_mshFile.eof())
104  {
105  if (line.find("ZONE") != string::npos)
106  {
107  ReadZone(nComposite);
108  }
109  }
110 
111  PrintSummary();
112  m_mshFile.reset();
113 
114  ProcessEdges();
115  ProcessFaces();
116  ProcessElements();
118 }
io::filtering_istream m_mshFile
Input stream.
NEKMESHUTILS_EXPORT void PrintSummary()
Print summary of elements.
NEKMESHUTILS_EXPORT void OpenStream()
Open a file for input.
virtual NEKMESHUTILS_EXPORT void ProcessFaces(bool ReprocessFaces=true)
Extract element faces.
virtual NEKMESHUTILS_EXPORT void ProcessElements()
Generate element IDs.
void ReadZone(int &nComposite)
virtual NEKMESHUTILS_EXPORT void ProcessEdges(bool ReprocessEdges=true)
Extract element edges.
virtual NEKMESHUTILS_EXPORT void ProcessComposites()
Generate composites.

◆ ReadZone()

void Nektar::Utilities::InputTec::ReadZone ( int &  nComposite)

Definition at line 120 of file InputStarTec.cpp.

References ASSERTL0, GenElement2D(), GenElement3D(), Nektar::NekMeshUtils::Module::m_mesh, Nektar::NekMeshUtils::InputModule::m_mshFile, class_topology::Node, Nektar::Utilities::PrismLineFaces(), Nektar::NekMeshUtils::Module::ProcessVertices(), and ResetNodes().

Referenced by Process().

121 {
122  int i;
123  string line, tag;
124  int nfaces, nnodes, nelements;
125  int start, end;
126  stringstream s;
127  NekDouble value;
128  static int zcnt = 1;
129 
130  // Read Zone Header
131  nnodes = nfaces = nelements = 0;
132  while (!m_mshFile.eof())
133  {
134  getline(m_mshFile, line);
135 
136  boost::to_upper(line);
137 
138  // cehck to see if readable data.
139  if (sscanf(line.c_str(), "%lf", &value) == 1)
140  {
141  break;
142  }
143 
144  if ((line.find("NODES") != string::npos) &&
145  (line.find("TOTALNUMFACENODES") == string::npos))
146  {
147  s.clear();
148  s.str(line);
149 
150  tag = s.str();
151  start = tag.find("NODES=");
152  end = tag.find_first_of(',', start);
153  nnodes = atoi(tag.substr(start + 6, end).c_str());
154  }
155 
156  if ((line.find("FACES") != string::npos) &&
157  (line.find("NUMCONNECTEDBOUNDARYFACES") == string::npos))
158  {
159  s.clear();
160  s.str(line);
161 
162  tag = s.str();
163  start = tag.find("FACES=");
164  end = tag.find_first_of(',', start);
165  nfaces = atoi(tag.substr(start + 6, end).c_str());
166  }
167 
168  if (line.find("ELEMENTS") != string::npos)
169  {
170  s.clear();
171  s.str(line);
172 
173  tag = s.str();
174  start = tag.find("ELEMENTS=");
175  end = tag.find_first_of(',', start);
176  nelements = atoi(tag.substr(start + 9, end).c_str());
177  }
178 
179  if (line.find("ZONETYPE") != string::npos)
180  {
181  s.clear();
182  s.str(line);
183 
184  if ((line.find("FEPOLYGON") == string::npos) &&
185  (line.find("FEPOLYHEDRON") == string::npos))
186  {
187  ASSERTL0(false,
188  "Routine only set up for FEPolygon or FEPolyhedron");
189  }
190  }
191  }
192  if (!nnodes) // No zone found
193  {
194  return;
195  }
196 
197  cout << "Setting up zone " << zcnt++;
198 
199  int nodeCount = 3 * nnodes;
200  vector<NekDouble> nodeLocs;
201 
202  while (nodeCount > 0 && !m_mshFile.eof())
203  {
204  s.clear();
205  s.str(line);
206  while (s >> value)
207  {
208  nodeLocs.push_back(value);
209  nodeCount--;
210  }
211  if (nodeCount > 0)
212  {
213  getline(m_mshFile, line);
214  }
215  }
216 
217  ASSERTL0(nodeLocs.size() == 3*nnodes, "Unable to read correct number of "
218  "nodes from Tecplot file");
219 
220  std::vector<NodeSharedPtr> Nodes;
221  for (i = 0; i < nnodes; ++i)
222  {
223  Nodes.push_back(
224  std::shared_ptr<Node>(
225  new Node(i, nodeLocs[i], nodeLocs[i+nnodes],
226  nodeLocs[i+2*nnodes])));
227  }
228 
229  // Read Node count per face
230  getline(m_mshFile, line);
231  if (line.find("node count per face") == string::npos)
232  {
233  if (line.find("face nodes") == string::npos)
234  {
235  getline(m_mshFile, line);
236  }
237  }
238 
239  s.clear();
240  s.str(line);
241 
242  vector<int> Nodes_per_face;
243  if (line.find("node count per face") != string::npos)
244  {
245  int nodes;
246  for (i = 0; i < nfaces; ++i)
247  {
248  m_mshFile >> nodes;
249  ASSERTL0(nodes <= 4,
250  "Can only handle meshes with "
251  "up to four nodes per face");
252  Nodes_per_face.push_back(nodes);
253  }
254  // Read next line
255  getline(m_mshFile, line);
256  }
257 
258  // Read face nodes;
259  if (line.find("face nodes") == string::npos)
260  {
261  getline(m_mshFile, line);
262  }
263  s.clear();
264  s.str(line);
265 
266  vector<vector<int> > FaceNodes;
267 
268  if (line.find("face nodes") != string::npos)
269  {
270 
271  for (i = 0; i < nfaces; ++i)
272  {
273  // check to see if Nodes_per_face is defined and
274  // if not assume 2 nodes for 2D case
275  int nodes = (Nodes_per_face.size()) ? Nodes_per_face[i] : 2;
276 
277  int nodeID;
278  vector<int> Fnodes;
279  for (int j = 0; j < nodes; ++j)
280  {
281 
282  m_mshFile >> nodeID;
283 
284  Fnodes.push_back(nodeID - 1);
285  }
286 
287  FaceNodes.push_back(Fnodes);
288  }
289  }
290  else
291  {
292  ASSERTL0(false, "Failed to find face node section");
293  }
294 
295  // Read left elements
296  Array<OneD, vector<int> > ElementFaces(nelements);
297 
298  // check to see if next line contains left elements
299  getline(m_mshFile, line);
300  if (line.find("left elements") == string::npos)
301  {
302  getline(m_mshFile, line);
303  }
304 
305  if (line.find("left elements") != string::npos)
306  {
307  int elmtID;
308 
309  for (i = 0; i < nfaces; ++i)
310  {
311  m_mshFile >> elmtID;
312 
313  if (elmtID > 0)
314  {
315  ElementFaces[elmtID - 1].push_back(i);
316  }
317  }
318  }
319  else
320  {
321  ASSERTL0(false, "Left element not found");
322  }
323 
324  // check to see if next line contains right elements
325  getline(m_mshFile, line);
326  if (line.find("right elements") == string::npos)
327  {
328  getline(m_mshFile, line);
329  }
330 
331  if (line.find("right elements") != string::npos)
332 
333  {
334  int elmtID;
335 
336  for (i = 0; i < nfaces; ++i)
337  {
338  m_mshFile >> elmtID;
339 
340  if (elmtID > 0)
341  {
342  ElementFaces[elmtID - 1].push_back(i);
343  }
344  }
345 
346  // read to end of line
347  getline(m_mshFile, line);
348  }
349  else
350  {
351  ASSERTL0(false, "Left element not found");
352  }
353 
354  if (Nodes_per_face.size()) // 3D Zone
355  {
356  cout << " (3D) " << endl;
357 
358  // Reset node ordering so that all prism faces have
359  // consistent numbering for singular vertex re-ordering
360  ResetNodes(Nodes, ElementFaces, FaceNodes);
361 
362  m_mesh->m_node = Nodes;
363 
364  // create Prisms/Pyramids first
365  for (i = 0; i < nelements; ++i)
366  {
367  if (ElementFaces[i].size() > 4)
368  {
369  GenElement3D(
370  Nodes, i, ElementFaces[i], FaceNodes, nComposite, true);
371  }
372  }
373 
374  nComposite++;
375 
376  // create Tets second
377  for (i = 0; i < nelements; ++i)
378  {
379  if (ElementFaces[i].size() == 4)
380  {
381  GenElement3D(
382  Nodes, i, ElementFaces[i], FaceNodes, nComposite, true);
383  }
384  }
385  nComposite++;
386 
387  ProcessVertices();
388  }
389  else // 2D Zone
390  {
391  cout << " (2D)" << endl;
392 
393  // find ids of VertNodes from m_mesh->m_vertexSet so that we can
394  // identify
395  for (i = 0; i < Nodes.size(); ++i)
396  {
397  auto it = m_mesh->m_vertexSet.find(Nodes[i]);
398 
399  if (it == m_mesh->m_vertexSet.end())
400  {
401  ASSERTL0(false, "Failed to find face vertex in 3D list");
402  }
403  else
404  {
405  Nodes[i] = *it;
406  }
407  }
408 
409  for (i = 0; i < nelements; ++i)
410  {
411  GenElement2D(Nodes, i, ElementFaces[i], FaceNodes, nComposite);
412  }
413 
414  nComposite++;
415  }
416 }
void GenElement3D(std::vector< NekMeshUtils::NodeSharedPtr > &Nodes, int i, std::vector< int > &ElementFaces, std::vector< std::vector< int > > &FaceNodes, int ncomposite, bool DoOrient)
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
io::filtering_istream m_mshFile
Input stream.
double NekDouble
virtual NEKMESHUTILS_EXPORT void ProcessVertices()
Extract element vertices.
void GenElement2D(std::vector< NekMeshUtils::NodeSharedPtr > &Nodes, int i, std::vector< int > &ElementFaces, std::vector< std::vector< int > > &FaceNodes, int ncomposite)
void ResetNodes(std::vector< NekMeshUtils::NodeSharedPtr > &Nodes, Array< OneD, std::vector< int > > &ElementFaces, std::vector< std::vector< int > > &FaceNodes)

◆ ResetNodes()

void Nektar::Utilities::InputTec::ResetNodes ( std::vector< NekMeshUtils::NodeSharedPtr > &  Nodes,
Array< OneD, std::vector< int > > &  ElementFaces,
std::vector< std::vector< int > > &  FaceNodes 
)
protected

Definition at line 424 of file InputStarTec.cpp.

References ASSERTL1, Nektar::Utilities::PrismLineFaces(), and SortFaceNodes().

Referenced by ReadZone().

427 {
428  int i, j;
429  Array<OneD, int> NodeReordering(Vnodes.size(), -1);
430  int face1_map[3] = {0, 1, 4};
431  int face3_map[3] = {3, 2, 5};
432  int nodeid = 0;
433  map<int, bool> FacesRenumbered;
434 
435  // Determine Prism triangular face connectivity.
436  vector<vector<int> > FaceToPrisms(FaceNodes.size());
437  vector<vector<int> > PrismToFaces(ElementFaces.num_elements());
438  map<int, int> Prisms;
439 
440  // generate map of prism-faces to prisms and prism to
441  // triangular-faces as well as ids of each prism.
442  for (i = 0; i < ElementFaces.num_elements(); ++i)
443  {
444  // Find Prism (and pyramids!).
445  if (ElementFaces[i].size() == 5)
446  {
447  vector<int> LocTriFaces;
448  // Find triangular faces
449  for (j = 0; j < ElementFaces[i].size(); ++j)
450  {
451  if (FaceNodes[ElementFaces[i][j]].size() == 3)
452  {
453  LocTriFaces.push_back(j);
454  }
455  }
456 
457  if (LocTriFaces.size() == 2) // prism otherwise a pyramid
458  {
459  Prisms[i] = i;
460 
461  PrismToFaces[i].push_back(ElementFaces[i][LocTriFaces[0]]);
462  PrismToFaces[i].push_back(ElementFaces[i][LocTriFaces[1]]);
463 
464  FaceToPrisms[ElementFaces[i][LocTriFaces[0]]].push_back(i);
465  FaceToPrisms[ElementFaces[i][LocTriFaces[1]]].push_back(i);
466  }
467  }
468  }
469 
470  vector<bool> FacesDone(FaceNodes.size(), false);
471  vector<bool> PrismDone(ElementFaces.num_elements(), false);
472 
473  // For every prism find the list of prismatic elements
474  // that represent an aligned block of cells. Then renumber
475  // these blocks consecutativiesly
476  for (auto &PrismIt : Prisms)
477  {
478  int elmtid = PrismIt.first;
479  map<int, int> facelist;
480 
481  if (PrismDone[elmtid])
482  {
483  continue;
484  }
485  else
486  {
487  // Generate list of faces in list
489  elmtid, facelist, FaceToPrisms, PrismToFaces, PrismDone);
490 
491  // loop over faces and number vertices of associated prisms.
492  for (auto &faceIt : facelist)
493  {
494  int faceid = faceIt.second;
495 
496  for (i = 0; i < FaceToPrisms[faceid].size(); ++i)
497  {
498  int prismid = FaceToPrisms[faceid][i];
499 
500  if ((FacesDone[PrismToFaces[prismid][0]] == true) &&
501  (FacesDone[PrismToFaces[prismid][1]] == true))
502  {
503  continue;
504  }
505 
506  Array<OneD, int> Nodes =
507  SortFaceNodes(Vnodes, ElementFaces[prismid], FaceNodes);
508 
509  if ((FacesDone[PrismToFaces[prismid][0]] == false) &&
510  (FacesDone[PrismToFaces[prismid][1]] == false))
511  {
512  // number all nodes consecutive since
513  // already correctly re-arranged.
514  for (i = 0; i < 3; ++i)
515  {
516  if (NodeReordering[Nodes[face1_map[i]]] == -1)
517  {
518  NodeReordering[Nodes[face1_map[i]]] = nodeid++;
519  }
520  }
521 
522  for (i = 0; i < 3; ++i)
523  {
524  if (NodeReordering[Nodes[face3_map[i]]] == -1)
525  {
526  NodeReordering[Nodes[face3_map[i]]] = nodeid++;
527  }
528  }
529  }
530  else if ((FacesDone[PrismToFaces[prismid][0]] == false) &&
531  (FacesDone[PrismToFaces[prismid][1]] == true))
532  {
533  // find node of highest id
534  int max_id1, max_id2;
535 
536  max_id1 = (NodeReordering[Nodes[face3_map[0]]] <
537  NodeReordering[Nodes[face3_map[1]]])
538  ? 1
539  : 0;
540  max_id2 = (NodeReordering[Nodes[face3_map[max_id1]]] <
541  NodeReordering[Nodes[face3_map[2]]])
542  ? 2
543  : max_id1;
544 
545  // add numbering according to order of
546  int id0 = (max_id1 == 1) ? 0 : 1;
547 
548  if (NodeReordering[Nodes[face1_map[id0]]] == -1)
549  {
550  NodeReordering[Nodes[face1_map[id0]]] = nodeid++;
551  }
552 
553  if (NodeReordering[Nodes[face1_map[max_id1]]] == -1)
554  {
555  NodeReordering[Nodes[face1_map[max_id1]]] =
556  nodeid++;
557  }
558 
559  if (NodeReordering[Nodes[face1_map[max_id2]]] == -1)
560  {
561  NodeReordering[Nodes[face1_map[max_id2]]] =
562  nodeid++;
563  }
564  }
565  else if ((FacesDone[PrismToFaces[prismid][0]] == true) &&
566  (FacesDone[PrismToFaces[prismid][1]] == false))
567  {
568  // find node of highest id
569  int max_id1, max_id2;
570 
571  max_id1 = (NodeReordering[Nodes[face1_map[0]]] <
572  NodeReordering[Nodes[face1_map[1]]])
573  ? 1
574  : 0;
575  max_id2 = (NodeReordering[Nodes[face1_map[max_id1]]] <
576  NodeReordering[Nodes[face1_map[2]]])
577  ? 2
578  : max_id1;
579 
580  // add numbering according to order of
581  int id0 = (max_id1 == 1) ? 0 : 1;
582 
583  if (NodeReordering[Nodes[face3_map[id0]]] == -1)
584  {
585  NodeReordering[Nodes[face3_map[id0]]] = nodeid++;
586  }
587 
588  if (NodeReordering[Nodes[face3_map[max_id1]]] == -1)
589  {
590  NodeReordering[Nodes[face3_map[max_id1]]] =
591  nodeid++;
592  }
593 
594  if (NodeReordering[Nodes[face3_map[max_id2]]] == -1)
595  {
596  NodeReordering[Nodes[face3_map[max_id2]]] =
597  nodeid++;
598  }
599  }
600  }
601  }
602  }
603  }
604 
605  // fill in any unset nodes at from other shapes
606  for (i = 0; i < NodeReordering.num_elements(); ++i)
607  {
608  if (NodeReordering[i] == -1)
609  {
610  NodeReordering[i] = nodeid++;
611  }
612  }
613 
614  ASSERTL1(nodeid == NodeReordering.num_elements(),
615  "Have not renumbered all nodes");
616 
617  // Renumbering successfull so resort nodes and faceNodes;
618  for (i = 0; i < FaceNodes.size(); ++i)
619  {
620  for (j = 0; j < FaceNodes[i].size(); ++j)
621  {
622  FaceNodes[i][j] = NodeReordering[FaceNodes[i][j]];
623  }
624  }
625 
626  vector<NodeSharedPtr> save(Vnodes);
627  for (i = 0; i < Vnodes.size(); ++i)
628  {
629  Vnodes[NodeReordering[i]] = save[i];
630  Vnodes[NodeReordering[i]]->SetID(NodeReordering[i]);
631  }
632 }
Array< OneD, int > SortFaceNodes(std::vector< NekMeshUtils::NodeSharedPtr > &Nodes, std::vector< int > &ElementFaces, std::vector< std::vector< int > > &FaceNodes)
static void PrismLineFaces(int prismid, map< int, int > &facelist, vector< vector< int > > &FacesToPrisms, vector< vector< int > > &PrismsToFaces, vector< bool > &PrismDone)
Definition: InputStar.cpp:420
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
Definition: ErrorUtil.hpp:250

◆ SortEdgeNodes()

Array< OneD, int > Nektar::Utilities::InputTec::SortEdgeNodes ( std::vector< NekMeshUtils::NodeSharedPtr > &  Nodes,
std::vector< int > &  ElementFaces,
std::vector< std::vector< int > > &  FaceNodes 
)
protected

Definition at line 779 of file InputStarTec.cpp.

References ASSERTL1, Nektar::NekMeshUtils::Node::curl(), and Nektar::NekMeshUtils::Node::dot().

Referenced by GenElement2D().

782 {
783  int i, j;
784  Array<OneD, int> returnval;
785 
786  if (ElementFaces.size() == 3) // Triangle
787  {
788  returnval = Array<OneD, int>(3);
789 
790  returnval[0] = FaceNodes[ElementFaces[0]][0];
791  returnval[1] = FaceNodes[ElementFaces[0]][1];
792 
793  // Find third node index;
794  for (i = 0; i < 2; ++i)
795  {
796  if ((FaceNodes[ElementFaces[1]][i] != returnval[0]) &&
797  (FaceNodes[ElementFaces[1]][i] != returnval[1]))
798  {
799  returnval[2] = FaceNodes[ElementFaces[1]][i];
800  break;
801  }
802  }
803  }
804  else if (ElementFaces.size() == 4) // quadrilateral
805  {
806  returnval = Array<OneD, int>(4);
807 
808  int indx0 = FaceNodes[ElementFaces[0]][0];
809  int indx1 = FaceNodes[ElementFaces[0]][1];
810  int indx2, indx3;
811 
812  indx2 = indx3 = -1;
813  // Find third, fourth node index;
814  for (j = 1; j < 4; ++j)
815  {
816  for (i = 0; i < 2; ++i)
817  {
818  if ((FaceNodes[ElementFaces[j]][i] != indx0) &&
819  (FaceNodes[ElementFaces[j]][i] != indx1))
820  {
821  if (indx2 == -1)
822  {
823  indx2 = FaceNodes[ElementFaces[j]][i];
824  }
825  else if (indx2 != -1)
826  {
827  if (FaceNodes[ElementFaces[j]][i] != indx2)
828  {
829  indx3 = FaceNodes[ElementFaces[j]][i];
830  }
831  }
832  }
833  }
834  }
835 
836  ASSERTL1((indx2 != -1) && (indx3 != -1),
837  "Failed to find vertex 3 or 4");
838 
839  // calculate 0-1,
840  Node a = *(Vnodes[indx1]) - *(Vnodes[indx0]);
841  // calculate 0-2,
842  Node b = *(Vnodes[indx2]) - *(Vnodes[indx0]);
843  Node acurlb = a.curl(b);
844 
845  // calculate 2-1,
846  Node c = *(Vnodes[indx1]) - *(Vnodes[indx2]);
847  // calculate 3-2,
848  Node d = *(Vnodes[indx3]) - *(Vnodes[indx2]);
849  Node acurld = a.curl(d);
850 
851  NekDouble acurlb_dot_acurld = acurlb.dot(acurld);
852  if (acurlb_dot_acurld > 0.0)
853  {
854  returnval[0] = indx0;
855  returnval[1] = indx1;
856  returnval[2] = indx2;
857  returnval[3] = indx3;
858  }
859  else
860  {
861  returnval[0] = indx0;
862  returnval[1] = indx1;
863  returnval[2] = indx3;
864  returnval[3] = indx2;
865  }
866  }
867 
868  return returnval;
869 }
NEKMESHUTILS_EXPORT NekDouble dot(const Node &pSrc) const
Definition: Node.h:161
Represents a point in the domain.
Definition: Node.h:62
double NekDouble
NEKMESHUTILS_EXPORT Node curl(const Node &pSrc) const
Definition: Node.h:166
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
Definition: ErrorUtil.hpp:250

◆ SortFaceNodes()

Array< OneD, int > Nektar::Utilities::InputTec::SortFaceNodes ( std::vector< NekMeshUtils::NodeSharedPtr > &  Nodes,
std::vector< int > &  ElementFaces,
std::vector< std::vector< int > > &  FaceNodes 
)
protected

Definition at line 871 of file InputStarTec.cpp.

References ASSERTL0, ASSERTL1, Nektar::NekMeshUtils::Node::curl(), and Nektar::NekMeshUtils::Node::dot().

Referenced by GenElement3D(), and ResetNodes().

874 {
875 
876  int i, j;
877  Array<OneD, int> returnval;
878 
879  if (ElementFaces.size() == 4) // Tetrahedron
880  {
881  ASSERTL1(FaceNodes[ElementFaces[0]].size() == 3,
882  "Face is not triangular");
883 
884  returnval = Array<OneD, int>(4);
885 
886  int indx0 = FaceNodes[ElementFaces[0]][0];
887  int indx1 = FaceNodes[ElementFaces[0]][1];
888  int indx2 = FaceNodes[ElementFaces[0]][2];
889  int indx3 = -1;
890 
891  // calculate 0-1,
892  Node a = *(Vnodes[indx1]) - *(Vnodes[indx0]);
893  // calculate 0-2,
894  Node b = *(Vnodes[indx2]) - *(Vnodes[indx0]);
895 
896  // Find fourth node index;
897  ASSERTL1(FaceNodes[ElementFaces[1]].size() == 3,
898  "Face is not triangular");
899  for (i = 0; i < 3; ++i)
900  {
901 
902  if ((FaceNodes[ElementFaces[1]][i] != indx0) &&
903  (FaceNodes[ElementFaces[1]][i] != indx1) &&
904  (FaceNodes[ElementFaces[1]][i] != indx2))
905  {
906  indx3 = FaceNodes[ElementFaces[1]][i];
907  break;
908  }
909  }
910 
911  // calculate 0-3,
912  Node c = *(Vnodes[indx3]) - *(Vnodes[indx0]);
913  Node acurlb = a.curl(b);
914 
915  NekDouble acurlb_dotc = acurlb.dot(c);
916  if (acurlb_dotc < 0.0)
917  {
918  returnval[0] = indx0;
919  returnval[1] = indx1;
920  returnval[2] = indx2;
921  returnval[3] = indx3;
922  }
923  else
924  {
925  returnval[0] = indx1;
926  returnval[1] = indx0;
927  returnval[2] = indx2;
928  returnval[3] = indx3;
929  }
930  }
931  else if (ElementFaces.size() == 5) // prism or pyramid
932  {
933  int triface0, triface1;
934  int quadface0, quadface1, quadface2;
935  bool isPrism = true;
936 
937  // find ids of tri faces and first quad face
938  triface0 = triface1 = -1;
939  quadface0 = quadface1 = quadface2 = -1;
940  for (i = 0; i < 5; ++i)
941  {
942  if (FaceNodes[ElementFaces[i]].size() == 3)
943  {
944  if (triface0 == -1)
945  {
946  triface0 = i;
947  }
948  else if (triface1 == -1)
949  {
950  triface1 = i;
951  }
952  else
953  {
954  isPrism = false;
955  }
956  }
957 
958  if (FaceNodes[ElementFaces[i]].size() == 4)
959  {
960  if (quadface0 == -1)
961  {
962  quadface0 = i;
963  }
964  else if (quadface1 == -1)
965  {
966  quadface1 = i;
967  }
968  else if (quadface2 == -1)
969  {
970  quadface2 = i;
971  }
972  }
973  }
974 
975  if (isPrism) // Prism
976  {
977  returnval = Array<OneD, int>(6);
978  }
979  else // Pyramid
980  {
981  returnval = Array<OneD, int>(5);
982  }
983 
984  // find matching nodes between triface0 and triquad0
985  int indx0, indx1, indx2, indx3, indx4;
986 
987  indx0 = indx1 = indx2 = indx3 = indx4 = -1;
988  // Loop over all quad nodes and if they match any
989  // triangular nodes If they do set these to indx0 and
990  // indx1 and if not set it to indx2, indx3
991 
992  for (i = 0; i < 4; ++i)
993  {
994  for (j = 0; j < 3; ++j)
995  {
996  if (FaceNodes[ElementFaces[triface0]][j] ==
997  FaceNodes[ElementFaces[quadface0]][i])
998  {
999  break; // same node break
1000  }
1001  }
1002 
1003  if (j == 3) // Vertex not in quad face
1004  {
1005  if (indx2 == -1)
1006  {
1007  indx2 = FaceNodes[ElementFaces[quadface0]][i];
1008  }
1009  else if (indx3 == -1)
1010  {
1011  indx3 = FaceNodes[ElementFaces[quadface0]][i];
1012  }
1013  else
1014  {
1015  ASSERTL0(
1016  false,
1017  "More than two vertices do not match triangular face");
1018  }
1019  }
1020  else // if found match then set indx0,indx1;
1021  {
1022  if (indx0 == -1)
1023  {
1024  indx0 = FaceNodes[ElementFaces[quadface0]][i];
1025  }
1026  else
1027  {
1028  indx1 = FaceNodes[ElementFaces[quadface0]][i];
1029  }
1030  }
1031  }
1032 
1033  // Finally check for top vertex
1034  for (int i = 0; i < 3; ++i)
1035  {
1036  if ((FaceNodes[ElementFaces[triface0]][i] != indx0) &&
1037  (FaceNodes[ElementFaces[triface0]][i] != indx1) &&
1038  (FaceNodes[ElementFaces[triface0]][i] != indx2))
1039  {
1040  indx4 = FaceNodes[ElementFaces[triface0]][i];
1041  break;
1042  }
1043  }
1044 
1045  // calculate 0-1,
1046  Node a = *(Vnodes[indx1]) - *(Vnodes[indx0]);
1047  // calculate 0-4,
1048  Node b = *(Vnodes[indx4]) - *(Vnodes[indx0]);
1049  // calculate 0-2,
1050  Node c = *(Vnodes[indx2]) - *(Vnodes[indx0]);
1051  Node acurlb = a.curl(b);
1052 
1053  NekDouble acurlb_dotc = acurlb.dot(c);
1054  if (acurlb_dotc < 0.0)
1055  {
1056  returnval[0] = indx0;
1057  returnval[1] = indx1;
1058  returnval[4] = indx4;
1059  }
1060  else
1061  {
1062  returnval[0] = indx1;
1063  returnval[1] = indx0;
1064  returnval[4] = indx4;
1065  }
1066 
1067  // check to see if two vertices are shared between one of the other
1068  // faces
1069  // to define which is indx2 and indx3
1070 
1071  int cnt = 0;
1072  for (int i = 0; i < 4; ++i)
1073  {
1074  if ((FaceNodes[ElementFaces[quadface1]][i] == returnval[1]) ||
1075  (FaceNodes[ElementFaces[quadface1]][i] == indx2))
1076  {
1077  cnt++;
1078  }
1079  }
1080 
1081  if (cnt == 2) // have two matching vertices
1082  {
1083  returnval[2] = indx2;
1084  returnval[3] = indx3;
1085  }
1086  else
1087  {
1088  cnt = 0;
1089  for (int i = 0; i < 4; ++i)
1090  {
1091  if ((FaceNodes[ElementFaces[quadface2]][i] == returnval[1]) ||
1092  (FaceNodes[ElementFaces[quadface2]][i] == indx2))
1093  {
1094  cnt++;
1095  }
1096  }
1097 
1098  if (cnt != 2) // neither of the other faces has two matching nodes
1099  // so reverse
1100  {
1101  returnval[2] = indx3;
1102  returnval[3] = indx2;
1103  }
1104  else // have two matching vertices
1105  {
1106  returnval[2] = indx2;
1107  returnval[3] = indx3;
1108  }
1109  }
1110 
1111  if (isPrism == true)
1112  {
1113  // finally need to find last vertex from second triangular face.
1114  for (int i = 0; i < 3; ++i)
1115  {
1116  if ((FaceNodes[ElementFaces[triface1]][i] != indx2) &&
1117  (FaceNodes[ElementFaces[triface1]][i] != indx3) &&
1118  (FaceNodes[ElementFaces[triface1]][i] != indx3))
1119  {
1120  returnval[5] = FaceNodes[ElementFaces[triface1]][i];
1121  break;
1122  }
1123  }
1124  }
1125  }
1126  else
1127  {
1128  ASSERTL0(false, "SortFaceNodes not set up for this number of faces");
1129  }
1130 
1131  return returnval;
1132 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
NEKMESHUTILS_EXPORT NekDouble dot(const Node &pSrc) const
Definition: Node.h:161
Represents a point in the domain.
Definition: Node.h:62
double NekDouble
NEKMESHUTILS_EXPORT Node curl(const Node &pSrc) const
Definition: Node.h:166
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
Definition: ErrorUtil.hpp:250

Member Data Documentation

◆ className

ModuleKey Nektar::Utilities::InputTec::className
static
Initial value:
"Reads Tecplot polyhedron ascii format converted from Star CCM (.dat).")

Definition at line 53 of file InputStarTec.h.