Nektar++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
Tetrahedron.cpp
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // File: Tetrahedron.cpp
4 //
5 // For more information, please see: http://www.nektar.info/
6 //
7 // The MIT License
8 //
9 // Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10 // Department of Aeronautics, Imperial College London (UK), and Scientific
11 // Computing and Imaging Institute, University of Utah (USA).
12 //
13 // License for the specific language governing rights and limitations under
14 // Permission is hereby granted, free of charge, to any person obtaining a
15 // copy of this software and associated documentation files (the "Software"),
16 // to deal in the Software without restriction, including without limitation
17 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 // and/or sell copies of the Software, and to permit persons to whom the
19 // Software is furnished to do so, subject to the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be included
22 // in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 // DEALINGS IN THE SOFTWARE.
31 //
32 // Description: Mesh tet object.
33 //
34 ////////////////////////////////////////////////////////////////////////////////
35 
37 #include <LocalRegions/TetExp.h>
38 #include <SpatialDomains/TetGeom.h>
39 
42 
44 
45 using namespace std;
46 
47 namespace Nektar
48 {
49 namespace NekMeshUtils
50 {
51 
52 LibUtilities::ShapeType Tetrahedron::m_type =
54  LibUtilities::eTetrahedron, Tetrahedron::create, "Tetrahedron");
55 
56 /// Vertex IDs that make up tetrahedron faces.
57 int Tetrahedron::m_faceIds[4][3] = {
58  {0, 1, 2}, {0, 1, 3}, {1, 2, 3}, {0, 2, 3}
59 };
60 
61 /**
62  * @brief Create a tetrahedron element.
63  */
64 Tetrahedron::Tetrahedron(ElmtConfig pConf,
65  vector<NodeSharedPtr> pNodeList,
66  vector<int> pTagList)
67  : Element(pConf, GetNumNodes(pConf), pNodeList.size())
68 {
69  m_tag = "A";
70  m_dim = 3;
71  m_taglist = pTagList;
72  int n = m_conf.m_order - 1;
73 
74  // Create a map to relate edge nodes to a pair of vertices
75  // defining an edge.
76  map<pair<int, int>, int> edgeNodeMap;
77  map<pair<int, int>, int>::iterator it;
78  edgeNodeMap[pair<int, int>(1, 2)] = 5;
79  edgeNodeMap[pair<int, int>(2, 3)] = 5 + n;
80  edgeNodeMap[pair<int, int>(1, 3)] = 5 + 2 * n;
81  edgeNodeMap[pair<int, int>(1, 4)] = 5 + 3 * n;
82  edgeNodeMap[pair<int, int>(2, 4)] = 5 + 4 * n;
83  edgeNodeMap[pair<int, int>(3, 4)] = 5 + 5 * n;
84 
85  // Add vertices
86  for (int i = 0; i < 4; ++i)
87  {
88  m_vertex.push_back(pNodeList[i]);
89  }
90 
91  // Create edges (with corresponding set of edge points)
92  int eid = 0;
93  for (it = edgeNodeMap.begin(); it != edgeNodeMap.end(); ++it)
94  {
95  vector<NodeSharedPtr> edgeNodes;
96  if (m_conf.m_order > 1)
97  {
98  for (int j = it->second; j < it->second + n; ++j)
99  {
100  edgeNodes.push_back(pNodeList[j - 1]);
101  }
102  }
103  m_edge.push_back(EdgeSharedPtr(new Edge(pNodeList[it->first.first - 1],
104  pNodeList[it->first.second - 1],
105  edgeNodes,
107  m_edge.back()->m_id = eid++;
108  }
109 
110  // Reorient the tet to ensure collapsed coordinates align between
111  // adjacent elements.
112  if (m_conf.m_reorient)
113  {
114  OrientTet();
115  }
116  else
117  {
118  // If we didn't need to orient the tet then set up the
119  // orientation map as the identity mapping.
120  for (int i = 0; i < 4; ++i)
121  {
122  m_orientationMap[i] = i;
123  }
124  }
125 
126  // Face-edge IDs
127  int face_edges[4][3];
128 
129  // Create faces
130  for (int j = 0; j < 4; ++j)
131  {
132  vector<NodeSharedPtr> faceVertices;
133  vector<EdgeSharedPtr> faceEdges;
134  vector<NodeSharedPtr> faceNodes;
135 
136  // Extract the edges for this face. We need to do this because
137  // of the reorientation which might have been applied (see the
138  // additional note below).
139  for (int k = 0; k < 3; ++k)
140  {
141  faceVertices.push_back(m_vertex[m_faceIds[j][k]]);
142  NodeSharedPtr a = m_vertex[m_faceIds[j][k]];
143  NodeSharedPtr b = m_vertex[m_faceIds[j][(k + 1) % 3]];
144  for (unsigned int i = 0; i < m_edge.size(); ++i)
145  {
146  if (((*(m_edge[i]->m_n1) == *a) &&
147  (*(m_edge[i]->m_n2) == *b)) ||
148  ((*(m_edge[i]->m_n1) == *b) && (*(m_edge[i]->m_n2) == *a)))
149  {
150  face_edges[j][k] = i;
151  faceEdges.push_back(m_edge[i]);
152  break;
153  }
154  }
155  }
156 
157  // When face curvature is supplied, it may have been the case
158  // that our tetrahedron was reoriented. In this case, faces have
159  // different vertex IDs and so we have to rotate the face
160  // curvature so that the two align appropriately.
161  if (m_conf.m_faceNodes)
162  {
163  const int nFaceNodes = n * (n - 1) / 2;
164 
165  // Get the vertex IDs of whatever face we are processing.
166  vector<int> faceVertIds(3);
167  faceVertIds[0] = faceVertices[0]->m_id;
168  faceVertIds[1] = faceVertices[1]->m_id;
169  faceVertIds[2] = faceVertices[2]->m_id;
170 
171  // Find out the original face number as we were given it in
172  // the constructor using the orientation map.
173  int origFace = -1;
174  for (int i = 0; i < 4; ++i)
175  {
176  if (m_orientationMap[i] == j)
177  {
178  origFace = i;
179  break;
180  }
181  }
182 
183  ASSERTL0(origFace >= 0, "Couldn't find face");
184 
185  // Now get the face nodes for the original face.
186  int N = 4 + 6 * n + origFace * nFaceNodes;
187  for (int i = 0; i < nFaceNodes; ++i)
188  {
189  faceNodes.push_back(pNodeList[N + i]);
190  }
191 
192  // Find the original face vertex IDs.
193  vector<int> origFaceIds(3);
194  origFaceIds[0] = pNodeList[m_faceIds[origFace][0]]->m_id;
195  origFaceIds[1] = pNodeList[m_faceIds[origFace][1]]->m_id;
196  origFaceIds[2] = pNodeList[m_faceIds[origFace][2]]->m_id;
197 
198  // Construct a HOTriangle object which performs the
199  // orientation magically for us.
200  HOTriangle<NodeSharedPtr> hoTri(origFaceIds, faceNodes);
201  hoTri.Align(faceVertIds);
202 
203  // Copy the face nodes back again.
204  faceNodes = hoTri.surfVerts;
205  }
206 
207  m_face.push_back(FaceSharedPtr(new Face(
208  faceVertices, faceNodes, faceEdges, m_conf.m_faceCurveType)));
209  }
210 
211  if (m_conf.m_volumeNodes)
212  {
213  const int nFaceNodes = n * (n - 1) / 2;
214  for (int i = 4 + 6 * n + 4 * nFaceNodes; i < pNodeList.size(); ++i)
215  {
216  m_volumeNodes.push_back(pNodeList[i]);
217  }
218  }
219 
220  vector<EdgeSharedPtr> tmp(6);
221  tmp[0] = m_edge[face_edges[0][0]];
222  tmp[1] = m_edge[face_edges[0][1]];
223  tmp[2] = m_edge[face_edges[0][2]];
224  tmp[3] = m_edge[face_edges[1][2]];
225  tmp[4] = m_edge[face_edges[1][1]];
226  tmp[5] = m_edge[face_edges[2][1]];
227  m_edge = tmp;
228 }
229 
231 {
234 
235  for (int i = 0; i < 4; ++i)
236  {
237  tfaces[i] = boost::dynamic_pointer_cast<SpatialDomains::TriGeom>(
238  m_face[i]->GetGeom(coordDim));
239  }
240 
242 
243  return ret;
244 }
245 
247  int edgeId, EdgeSharedPtr edge)
248 {
249  static int edgeVerts[6][2] = { {0,1}, {1,2}, {0,2}, {0,3}, {1,3}, {2,3} };
250 
251  if (edge->m_n1 == m_vertex[edgeVerts[edgeId][0]])
252  {
253  return StdRegions::eForwards;
254  }
255  else if (edge->m_n1 == m_vertex[edgeVerts[edgeId][1]])
256  {
257  return StdRegions::eBackwards;
258  }
259  else
260  {
261  ASSERTL1(false, "Edge is not connected to this quadrilateral.");
262  }
263 
265 }
266 
267 void Tetrahedron::MakeOrder(int order,
270  int coordDim,
271  int &id,
272  bool justConfig)
273 {
274  m_conf.m_order = order;
275  m_curveType = pType;
276  m_volumeNodes.clear();
277 
278  if (order == 1 || order == 2)
279  {
281  return;
282  }
283  else if (order == 2)
284  {
285  m_conf.m_faceNodes = true;
286  m_conf.m_volumeNodes = false;
287  return;
288  }
289  else if (order == 3)
290  {
291  m_conf.m_volumeNodes = false;
292  return;
293  }
294 
295  m_conf.m_faceNodes = true;
296  m_conf.m_volumeNodes = true;
297 
298  if (justConfig)
299  {
300  return;
301  }
302 
303  int nPoints = order + 1;
304  StdRegions::StdExpansionSharedPtr xmap = geom->GetXmap();
305 
306  Array<OneD, NekDouble> px, py, pz;
307  LibUtilities::PointsKey pKey(nPoints, pType);
308  ASSERTL1(pKey.GetPointsDim() == 3, "Points distribution must be 3D");
309  LibUtilities::PointsManager()[pKey]->GetPoints(px, py, pz);
310 
311  Array<OneD, Array<OneD, NekDouble> > phys(coordDim);
312 
313  for (int i = 0; i < coordDim; ++i)
314  {
315  phys[i] = Array<OneD, NekDouble>(xmap->GetTotPoints());
316  xmap->BwdTrans(geom->GetCoeffs(i), phys[i]);
317  }
318 
319  const int nTetPts = nPoints * (nPoints + 1) * (nPoints + 2) / 6;
320  const int nTetIntPts = (nPoints - 4) * (nPoints - 3) * (nPoints - 2) / 6;
321  m_volumeNodes.resize(nTetIntPts);
322 
323  for (int i = nTetPts - nTetIntPts, cnt = 0; i < nTetPts; ++i, ++cnt)
324  {
326  xp[0] = px[i];
327  xp[1] = py[i];
328  xp[2] = pz[i];
329 
330  Array<OneD, NekDouble> x(3, 0.0);
331  for (int j = 0; j < coordDim; ++j)
332  {
333  x[j] = xmap->PhysEvaluate(xp, phys[j]);
334  }
335 
336  m_volumeNodes[cnt] = boost::shared_ptr<Node>(
337  new Node(id++, x[0], x[1], x[2]));
338  }
339 }
340 
341 /**
342  * @brief Return the number of nodes defining a tetrahedron.
343  */
345 {
346  int n = pConf.m_order;
347  if (pConf.m_volumeNodes && pConf.m_faceNodes)
348  return (n + 1) * (n + 2) * (n + 3) / 6;
349  else if (!pConf.m_volumeNodes && pConf.m_faceNodes)
350  return 4 * (n + 1) * (n + 2) / 2 - 6 * (n + 1) + 4;
351  else
352  return 6 * (n + 1) - 8;
353 }
354 
355 struct TetOrient
356 {
357  TetOrient(vector<int> nid, int fid) : nid(nid), fid(fid)
358  {
359  }
360  vector<int> nid;
361  int fid;
362 };
363 
364 struct TetOrientHash : std::unary_function<struct TetOrient, std::size_t>
365 {
366  std::size_t operator()(struct TetOrient const &p) const
367  {
368  return boost::hash_range(p.nid.begin(), p.nid.end());
369  }
370 };
371 typedef boost::unordered_set<struct TetOrient, TetOrientHash> TetOrientSet;
372 
373 bool operator==(const struct TetOrient &a, const struct TetOrient &b)
374 {
375  if (a.nid.size() != b.nid.size())
376  {
377  return false;
378  }
379 
380  for (int i = 0; i < a.nid.size(); ++i)
381  {
382  if (a.nid[i] != b.nid[i])
383  {
384  return false;
385  }
386  }
387 
388  return true;
389 }
390 
391 void Tetrahedron::GetCurvedNodes(std::vector<NodeSharedPtr> &nodeList) const
392 {
393  int n = m_edge[0]->GetNodeCount();
394  nodeList.resize(n*(n+1)*(n+2)/6);
395 
396  nodeList[0] = m_vertex[0];
397  nodeList[1] = m_vertex[1];
398  nodeList[2] = m_vertex[2];
399  nodeList[3] = m_vertex[3];
400  int k = 4;
401 
402  for(int i = 0; i < 6; i++)
403  {
404  bool reverseEdge = false;
405  if(i < 3)
406  {
407  reverseEdge = m_edge[i]->m_n1 == m_vertex[i];
408  }
409  else
410  {
411  reverseEdge = m_edge[i]->m_n1 == m_vertex[i-3];
412  }
413 
414  if (reverseEdge)
415  {
416  for(int j = 0; j < n-2; j++)
417  {
418  nodeList[k++] = m_edge[i]->m_edgeNodes[j];
419  }
420  }
421  else
422  {
423  for(int j = n-3; j >= 0; j--)
424  {
425  nodeList[k++] = m_edge[i]->m_edgeNodes[j];
426  }
427  }
428  }
429 
430  vector<vector<int> > ts;
431  vector<int> t(3);
432  t[0] = m_vertex[0]->m_id;
433  t[1] = m_vertex[1]->m_id;
434  t[2] = m_vertex[2]->m_id;
435  ts.push_back(t);
436  t[0] = m_vertex[0]->m_id;
437  t[1] = m_vertex[1]->m_id;
438  t[2] = m_vertex[3]->m_id;
439  ts.push_back(t);
440  t[0] = m_vertex[1]->m_id;
441  t[1] = m_vertex[2]->m_id;
442  t[2] = m_vertex[3]->m_id;
443  ts.push_back(t);
444  t[0] = m_vertex[0]->m_id;
445  t[1] = m_vertex[2]->m_id;
446  t[2] = m_vertex[3]->m_id;
447  ts.push_back(t);
448 
449  for(int i = 0; i < 4; i++)
450  {
451  vector<int> fcid;
452  fcid.push_back(m_face[i]->m_vertexList[0]->m_id);
453  fcid.push_back(m_face[i]->m_vertexList[1]->m_id);
454  fcid.push_back(m_face[i]->m_vertexList[2]->m_id);
455 
456  HOTriangle<NodeSharedPtr> hot(fcid, m_face[i]->m_faceNodes);
457 
458  hot.Align(ts[i]);
459 
460  std::copy(hot.surfVerts.begin(),
461  hot.surfVerts.end(),
462  nodeList.begin() + k);
463  k+= hot.surfVerts.size();
464  }
465 
466  std::copy(m_volumeNodes.begin(),
467  m_volumeNodes.end(),
468  nodeList.begin() + k);
469 }
470 
471 /**
472  * @brief Orient tetrahedron to align degenerate vertices.
473  *
474  * Orientation of tetrahedral elements is required so that the
475  * singular vertices of triangular faces (which occur as a part of the
476  * collapsed co-ordinate system) align. The algorithm is based on that
477  * used in T. Warburton's thesis and in the original Nektar source.
478  *
479  * First the vertices are ordered with the highest global vertex at
480  * the top degenerate point, and the base degenerate point has second
481  * lowest ID. These vertices are swapped if the element is incorrectly
482  * oriented.
483  */
485 {
486  TetOrientSet faces;
487 
488  // Create a copy of the original vertex ordering. This is used to
489  // construct a mapping, #orientationMap, which maps the original
490  // face ordering to the new face ordering.
491  for (int i = 0; i < 4; ++i)
492  {
493  vector<int> nodes(3);
494 
495  nodes[0] = m_vertex[m_faceIds[i][0]]->m_id;
496  nodes[1] = m_vertex[m_faceIds[i][1]]->m_id;
497  nodes[2] = m_vertex[m_faceIds[i][2]]->m_id;
498 
499  sort(nodes.begin(), nodes.end());
500  struct TetOrient faceNodes(nodes, i);
501  faces.insert(faceNodes);
502  }
503 
504  // Store a copy of the original vertex ordering so we can create a
505  // permutation map later.
506  vector<NodeSharedPtr> origVert = m_vertex;
507 
508  // Order vertices with highest global vertex at top degenerate
509  // point. Place second highest global vertex at base degenerate
510  // point.
511  sort(m_vertex.begin(), m_vertex.end());
512 
513  // Calculate a.(b x c) if negative, reverse order of
514  // non-degenerate points to correctly orientate the tet.
515 
516  NekDouble ax = m_vertex[1]->m_x - m_vertex[0]->m_x;
517  NekDouble ay = m_vertex[1]->m_y - m_vertex[0]->m_y;
518  NekDouble az = m_vertex[1]->m_z - m_vertex[0]->m_z;
519  NekDouble bx = m_vertex[2]->m_x - m_vertex[0]->m_x;
520  NekDouble by = m_vertex[2]->m_y - m_vertex[0]->m_y;
521  NekDouble bz = m_vertex[2]->m_z - m_vertex[0]->m_z;
522  NekDouble cx = m_vertex[3]->m_x - m_vertex[0]->m_x;
523  NekDouble cy = m_vertex[3]->m_y - m_vertex[0]->m_y;
524  NekDouble cz = m_vertex[3]->m_z - m_vertex[0]->m_z;
525 
526  NekDouble nx = (ay * bz - az * by);
527  NekDouble ny = (az * bx - ax * bz);
528  NekDouble nz = (ax * by - ay * bx);
529  NekDouble nmag = sqrt(nx * nx + ny * ny + nz * nz);
530  nx /= nmag;
531  ny /= nmag;
532  nz /= nmag;
533 
534  // distance of top vertex from base
535  NekDouble dist = cx * nx + cy * ny + cz * nz;
536 
537  if (fabs(dist) <= 1e-4)
538  {
539  cerr << "Warning: degenerate tetrahedron, 3rd vertex is = " << dist
540  << " from face" << endl;
541  }
542 
543  if (dist < 0)
544  {
545  swap(m_vertex[0], m_vertex[1]);
546  }
547 
548  nx = (ay * cz - az * cy);
549  ny = (az * cx - ax * cz);
550  nz = (ax * cy - ay * cx);
551  nmag = sqrt(nx * nx + ny * ny + nz * nz);
552  nx /= nmag;
553  ny /= nmag;
554  nz /= nmag;
555 
556  // distance of top vertex from base
557  dist = bx * nx + by * ny + bz * nz;
558 
559  if (fabs(dist) <= 1e-4)
560  {
561  cerr << "Warning: degenerate tetrahedron, 2nd vertex is = " << dist
562  << " from face" << endl;
563  }
564 
565  nx = (by * cz - bz * cy);
566  ny = (bz * cx - bx * cz);
567  nz = (bx * cy - by * cx);
568  nmag = sqrt(nx * nx + ny * ny + nz * nz);
569  nx /= nmag;
570  ny /= nmag;
571  nz /= nmag;
572 
573  // distance of top vertex from base
574  dist = ax * nx + ay * ny + az * nz;
575 
576  if (fabs(dist) <= 1e-4)
577  {
578  cerr << "Warning: degenerate tetrahedron, 1st vertex is = " << dist
579  << " from face" << endl;
580  }
581 
583 
584  // Search for the face in the original set of face nodes. Then use
585  // this to construct the #orientationMap.
586  for (int i = 0; i < 4; ++i)
587  {
588  vector<int> nodes(3);
589 
590  nodes[0] = m_vertex[m_faceIds[i][0]]->m_id;
591  nodes[1] = m_vertex[m_faceIds[i][1]]->m_id;
592  nodes[2] = m_vertex[m_faceIds[i][2]]->m_id;
593  sort(nodes.begin(), nodes.end());
594 
595  struct TetOrient faceNodes(nodes, 0);
596 
597  it = faces.find(faceNodes);
598  m_orientationMap[it->fid] = i;
599 
600  for (int j = 0; j < 4; ++j)
601  {
602  if (m_vertex[i]->m_id == origVert[j]->m_id)
603  {
604  m_origVertMap[j] = i;
605  break;
606  }
607  }
608  }
609 }
610 }
611 }
bool m_faceNodes
Denotes whether the element contains face nodes. For 2D elements, if this is true then the element co...
Definition: ElementConfig.h:80
virtual NEKMESHUTILS_EXPORT void GetCurvedNodes(std::vector< NodeSharedPtr > &nodeList) const
get list of volume interior nodes
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:198
Basic information about an element.
Definition: ElementConfig.h:50
LibUtilities::PointsType m_faceCurveType
Distribution of points in faces.
Definition: ElementConfig.h:94
virtual NEKMESHUTILS_EXPORT StdRegions::Orientation GetEdgeOrient(int edgeId, EdgeSharedPtr edge)
Get the edge orientation of edge with respect to the local element, which lies at edge index edgeId...
Represents an edge which joins two points.
Definition: Edge.h:58
static boost::shared_ptr< DataType > AllocateSharedPtr()
Allocate a shared pointer from the memory pool.
void Align(std::vector< int > vertId)
Align this surface to a given vertex ID.
Definition: HOAlignment.h:135
Represents a face comprised of three or more edges.
Definition: Face.h:61
virtual NEKMESHUTILS_EXPORT SpatialDomains::GeometrySharedPtr GetGeom(int coordDim)
Generate a Nektar++ geometry object for this element.
STL namespace.
std::vector< T > surfVerts
The triangle surface vertices – templated so that this can either be nodes or IDs.
Definition: HOAlignment.h:65
ElementFactory & GetElementFactory()
Definition: Element.cpp:47
ElmtConfig m_conf
Contains configuration of the element.
Definition: Element.h:380
std::vector< int > m_taglist
List of integers specifying properties of the element.
Definition: Element.h:384
bool operator==(ElmtConfig const &c1, ElmtConfig const &c2)
Compares two element config structs.
std::size_t operator()(struct TetOrient const &p) const
LibUtilities::PointsType m_edgeCurveType
Distribution of points in edges.
Definition: ElementConfig.h:92
unsigned int m_order
Order of the element.
Definition: ElementConfig.h:87
boost::unordered_set< struct TetOrient, TetOrientHash > TetOrientSet
std::vector< NodeSharedPtr > m_vertex
List of element vertex nodes.
Definition: Element.h:386
unsigned int m_dim
Dimension of the element.
Definition: Element.h:378
static int m_faceIds[4][3]
Vertex IDs that make up tetrahedron faces.
Definition: Tetrahedron.h:99
bool m_volumeNodes
Denotes whether the element contains volume (i.e. interior) nodes. These are not supported by either ...
Definition: ElementConfig.h:85
std::vector< EdgeSharedPtr > m_edge
List of element edges.
Definition: Element.h:388
unsigned int GetPointsDim() const
Definition: Points.h:149
boost::shared_ptr< Node > NodeSharedPtr
Definition: Node.h:50
PointsManagerT & PointsManager(void)
Defines a specification for a set of points.
Definition: Points.h:58
double NekDouble
std::vector< NodeSharedPtr > m_volumeNodes
List of element volume nodes.
Definition: Element.h:392
void OrientTet()
Orient tetrahedron to align degenerate vertices.
A lightweight struct for dealing with high-order triangle alignment.
Definition: HOAlignment.h:50
std::string m_tag
Tag character describing the element.
Definition: Element.h:382
boost::shared_ptr< Edge > EdgeSharedPtr
Shared pointer to an edge.
Definition: Edge.h:136
StandardMatrixTag boost::call_traits< LhsDataType >::const_reference rhs typedef NekMatrix< LhsDataType, StandardMatrixTag >::iterator iterator
static NEKMESHUTILS_EXPORT unsigned int GetNumNodes(ElmtConfig pConf)
Return the number of nodes defining a tetrahedron.
unsigned int m_id
ID of the element.
Definition: Element.h:376
boost::shared_ptr< TetGeom > TetGeomSharedPtr
Definition: TetGeom.h:106
boost::shared_ptr< TriGeom > TriGeomSharedPtr
Definition: TriGeom.h:58
virtual NEKMESHUTILS_EXPORT void MakeOrder(int order, SpatialDomains::GeometrySharedPtr geom, LibUtilities::PointsType pType, int coordDim, int &id, bool justConfig=false)
Insert interior (i.e. volume) points into this element to make the geometry an order order representa...
LibUtilities::PointsType m_curveType
Volume curve type.
Definition: Element.h:394
std::vector< FaceSharedPtr > m_face
List of element faces.
Definition: Element.h:390
bool m_reorient
Denotes whether the element needs to be re-orientated for a spectral element framework.
Definition: ElementConfig.h:90
boost::shared_ptr< Face > FaceSharedPtr
Definition: Face.h:153
boost::shared_ptr< StdExpansion > StdExpansionSharedPtr
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
Definition: ErrorUtil.hpp:228
boost::shared_ptr< Geometry > GeometrySharedPtr
Definition: Geometry.h:53
TetOrient(vector< int > nid, int fid)
Base class for element definitions.
Definition: Element.h:59
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, tDescription pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:215