49 namespace NekMeshUtils
57 int Tetrahedron::m_faceIds[4][3] = {
58 {0, 1, 2}, {0, 1, 3}, {1, 2, 3}, {0, 2, 3}
65 vector<NodeSharedPtr> pNodeList,
67 :
Element(pConf, GetNumNodes(pConf), pNodeList.size())
76 map<pair<int, int>,
int> edgeNodeMap;
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;
86 for (
int i = 0; i < 4; ++i)
93 for (it = edgeNodeMap.begin(); it != edgeNodeMap.end(); ++it)
95 vector<NodeSharedPtr> edgeNodes;
98 for (
int j = it->second; j < it->second + n; ++j)
100 edgeNodes.push_back(pNodeList[j - 1]);
104 pNodeList[it->first.second - 1],
107 m_edge.back()->m_id = eid++;
120 for (
int i = 0; i < 4; ++i)
127 int face_edges[4][3];
130 for (
int j = 0; j < 4; ++j)
132 vector<NodeSharedPtr> faceVertices;
133 vector<EdgeSharedPtr> faceEdges;
134 vector<NodeSharedPtr> faceNodes;
139 for (
int k = 0; k < 3; ++k)
144 for (
unsigned int i = 0; i <
m_edge.size(); ++i)
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)))
150 face_edges[j][k] = i;
151 faceEdges.push_back(
m_edge[i]);
163 const int nFaceNodes = n * (n - 1) / 2;
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;
174 for (
int i = 0; i < 4; ++i)
183 ASSERTL0(origFace >= 0,
"Couldn't find face");
186 int N = 4 + 6 * n + origFace * nFaceNodes;
187 for (
int i = 0; i < nFaceNodes; ++i)
189 faceNodes.push_back(pNodeList[N + i]);
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;
201 hoTri.
Align(faceVertIds);
213 const int nFaceNodes = n * (n - 1) / 2;
214 for (
int i = 4 + 6 * n + 4 * nFaceNodes; i < pNodeList.size(); ++i)
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]];
235 for (
int i = 0; i < 4; ++i)
238 m_face[i]->GetGeom(coordDim));
249 static int edgeVerts[6][2] = { {0,1}, {1,2}, {0,2}, {0,3}, {1,3}, {2,3} };
251 if (edge->m_n1 ==
m_vertex[edgeVerts[edgeId][0]])
255 else if (edge->m_n1 ==
m_vertex[edgeVerts[edgeId][1]])
261 ASSERTL1(
false,
"Edge is not connected to this quadrilateral.");
278 if (order == 1 || order == 2)
303 int nPoints = order + 1;
313 for (
int i = 0; i < coordDim; ++i)
316 xmap->BwdTrans(geom->GetCoeffs(i), phys[i]);
319 const int nTetPts = nPoints * (nPoints + 1) * (nPoints + 2) / 6;
320 const int nTetIntPts = (nPoints - 4) * (nPoints - 3) * (nPoints - 2) / 6;
323 for (
int i = nTetPts - nTetIntPts, cnt = 0; i < nTetPts; ++i, ++cnt)
331 for (
int j = 0; j < coordDim; ++j)
333 x[j] = xmap->PhysEvaluate(xp, phys[j]);
337 new Node(
id++, x[0], x[1], x[2]));
348 return (n + 1) * (n + 2) * (n + 3) / 6;
350 return 4 * (n + 1) * (n + 2) / 2 - 6 * (n + 1) + 4;
352 return 6 * (n + 1) - 8;
368 return boost::hash_range(p.
nid.begin(), p.
nid.end());
371 typedef boost::unordered_set<struct TetOrient, TetOrientHash>
TetOrientSet;
375 if (a.
nid.size() != b.
nid.size())
380 for (
int i = 0; i < a.
nid.size(); ++i)
393 int n =
m_edge[0]->GetNodeCount();
394 nodeList.resize(n*(n+1)*(n+2)/6);
402 for(
int i = 0; i < 6; i++)
404 bool reverseEdge =
false;
416 for(
int j = 0; j < n-2; j++)
418 nodeList[k++] =
m_edge[i]->m_edgeNodes[j];
423 for(
int j = n-3; j >= 0; j--)
425 nodeList[k++] =
m_edge[i]->m_edgeNodes[j];
430 vector<vector<int> > ts;
449 for(
int i = 0; i < 4; i++)
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);
462 nodeList.begin() + k);
468 nodeList.begin() + k);
491 for (
int i = 0; i < 4; ++i)
493 vector<int> nodes(3);
499 sort(nodes.begin(), nodes.end());
501 faces.insert(faceNodes);
506 vector<NodeSharedPtr> origVert =
m_vertex;
529 NekDouble nmag = sqrt(nx * nx + ny * ny + nz * nz);
535 NekDouble dist = cx * nx + cy * ny + cz * nz;
537 if (fabs(dist) <= 1e-4)
539 cerr <<
"Warning: degenerate tetrahedron, 3rd vertex is = " << dist
540 <<
" from face" << endl;
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);
557 dist = bx * nx + by * ny + bz * nz;
559 if (fabs(dist) <= 1e-4)
561 cerr <<
"Warning: degenerate tetrahedron, 2nd vertex is = " << dist
562 <<
" from face" << endl;
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);
574 dist = ax * nx + ay * ny + az * nz;
576 if (fabs(dist) <= 1e-4)
578 cerr <<
"Warning: degenerate tetrahedron, 1st vertex is = " << dist
579 <<
" from face" << endl;
586 for (
int i = 0; i < 4; ++i)
588 vector<int> nodes(3);
593 sort(nodes.begin(), nodes.end());
597 it = faces.find(faceNodes);
600 for (
int j = 0; j < 4; ++j)
bool m_faceNodes
Denotes whether the element contains face nodes. For 2D elements, if this is true then the element co...
virtual NEKMESHUTILS_EXPORT void GetCurvedNodes(std::vector< NodeSharedPtr > &nodeList) const
get list of volume interior nodes
#define ASSERTL0(condition, msg)
Basic information about an element.
LibUtilities::PointsType m_faceCurveType
Distribution of points in faces.
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.
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.
Represents a face comprised of three or more edges.
virtual NEKMESHUTILS_EXPORT SpatialDomains::GeometrySharedPtr GetGeom(int coordDim)
Generate a Nektar++ geometry object for this element.
std::vector< T > surfVerts
The triangle surface vertices – templated so that this can either be nodes or IDs.
ElementFactory & GetElementFactory()
ElmtConfig m_conf
Contains configuration of the element.
std::vector< int > m_taglist
List of integers specifying properties of the element.
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.
unsigned int m_order
Order of the element.
boost::unordered_set< struct TetOrient, TetOrientHash > TetOrientSet
std::vector< NodeSharedPtr > m_vertex
List of element vertex nodes.
unsigned int m_dim
Dimension of the element.
static int m_faceIds[4][3]
Vertex IDs that make up tetrahedron faces.
bool m_volumeNodes
Denotes whether the element contains volume (i.e. interior) nodes. These are not supported by either ...
std::vector< EdgeSharedPtr > m_edge
List of element edges.
unsigned int GetPointsDim() const
boost::shared_ptr< Node > NodeSharedPtr
PointsManagerT & PointsManager(void)
Defines a specification for a set of points.
std::vector< NodeSharedPtr > m_volumeNodes
List of element volume nodes.
void OrientTet()
Orient tetrahedron to align degenerate vertices.
A lightweight struct for dealing with high-order triangle alignment.
std::string m_tag
Tag character describing the element.
boost::shared_ptr< Edge > EdgeSharedPtr
Shared pointer to an edge.
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.
boost::shared_ptr< TetGeom > TetGeomSharedPtr
boost::shared_ptr< TriGeom > TriGeomSharedPtr
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.
std::vector< FaceSharedPtr > m_face
List of element faces.
bool m_reorient
Denotes whether the element needs to be re-orientated for a spectral element framework.
boost::shared_ptr< Face > FaceSharedPtr
boost::shared_ptr< StdExpansion > StdExpansionSharedPtr
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
boost::shared_ptr< Geometry > GeometrySharedPtr
TetOrient(vector< int > nid, int fid)
Base class for element definitions.
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, tDescription pDesc="")
Register a class with the factory.