Nektar++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Face.h
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // File: Face.h
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 manipulation objects.
33 //
34 ////////////////////////////////////////////////////////////////////////////////
35 
36 #ifndef NEKMESHUTILS_MESHELEMENTS_FACE
37 #define NEKMESHUTILS_MESHELEMENTS_FACE
38 
39 #include <SpatialDomains/TriGeom.h>
41 
44 
45 namespace Nektar
46 {
47 namespace NekMeshUtils
48 {
49 
50 class Element;
51 typedef boost::shared_ptr<Element> ElementSharedPtr;
52 
53 /**
54  * @brief Represents a face comprised of three or more edges.
55  *
56  * A face is defined by a list of vertices, a list of edges joining
57  * these vertices, and a list of control nodes within the interior of
58  * the face, defining the shape of the face.
59  */
60 class Face
61 {
62 public:
63  /// Create a new face.
64  Face(std::vector<NodeSharedPtr> pVertexList,
65  std::vector<NodeSharedPtr> pFaceNodes,
66  std::vector<EdgeSharedPtr> pEdgeList,
67  LibUtilities::PointsType pCurveType)
68  : m_vertexList(pVertexList), m_edgeList(pEdgeList),
69  m_faceNodes(pFaceNodes), m_curveType(pCurveType), m_geom()
70  {
71  }
72 
73  /// Copy an existing face.
74  Face(const Face &pSrc)
77  m_geom(pSrc.m_geom)
78  {
79  }
81  {
82  }
83 
84  /// Equality is defined by matching all vertices.
85  bool operator==(Face &pSrc)
86  {
88  for (it1 = m_vertexList.begin(); it1 != m_vertexList.end(); ++it1)
89  {
90  if (find(pSrc.m_vertexList.begin(),
91  pSrc.m_vertexList.end(),
92  *it1) == pSrc.m_vertexList.end())
93  {
94  return false;
95  }
96  }
97  return true;
98  }
99 
100  /// Returns the total number of nodes (vertices, edge nodes and
101  /// face nodes).
102  unsigned int GetNodeCount() const
103  {
104  unsigned int n = m_faceNodes.size();
105  for (int i = 0; i < m_edgeList.size(); ++i)
106  {
107  n += m_edgeList[i]->GetNodeCount();
108  }
109  n -= m_vertexList.size();
110  return n;
111  }
112 
113  /// Assemble a list of nodes on curved face
114  void GetCurvedNodes(std::vector<NodeSharedPtr> &nodeList) const
115  {
116  // Treat 2D point distributions differently to 3D.
120  {
121  int n = m_edgeList[0]->GetNodeCount();
122 
123  nodeList.insert(
124  nodeList.end(), m_vertexList.begin(), m_vertexList.end());
125  for (int k = 0; k < m_edgeList.size(); ++k)
126  {
127  nodeList.insert(nodeList.end(),
128  m_edgeList[k]->m_edgeNodes.begin(),
129  m_edgeList[k]->m_edgeNodes.end());
130  if (m_edgeList[k]->m_n1 != m_vertexList[k])
131  {
132  // If edge orientation is reversed relative to node
133  // ordering, we need to reverse order of nodes.
134  std::reverse(nodeList.begin() + 3 + k * (n - 2),
135  nodeList.begin() + 3 + (k + 1) * (n - 2));
136  }
137  }
138  nodeList.insert(
139  nodeList.end(), m_faceNodes.begin(), m_faceNodes.end());
140  }
141  else
142  {
143  // Write out in 2D tensor product order.
144  ASSERTL0(m_vertexList.size() == 4,
145  "Face nodes of tensor product only supported "
146  "for quadrilaterals.");
147 
148  int n = (int)sqrt((NekDouble)GetNodeCount());
149  nodeList.resize(n * n);
150 
151  ASSERTL0(n * n == GetNodeCount(), "Wrong number of modes?");
152 
153  // Write vertices
154  nodeList[0] = m_vertexList[0];
155  nodeList[n - 1] = m_vertexList[1];
156  nodeList[n * n - 1] = m_vertexList[2];
157  nodeList[n * (n - 1)] = m_vertexList[3];
158 
159  // Write edge-interior
160  int skips[4][2] = {
161  {0, 1}, {n - 1, n}, {n * n - 1, -1}, {n * (n - 1), -n}};
162  for (int i = 0; i < 4; ++i)
163  {
164  bool reverseEdge = m_edgeList[i]->m_n1 == m_vertexList[i];
165 
166  if (!reverseEdge)
167  {
168  for (int j = 1; j < n - 1; ++j)
169  {
170  nodeList[skips[i][0] + j * skips[i][1]] =
171  m_edgeList[i]->m_edgeNodes[n - 2 - j];
172  }
173  }
174  else
175  {
176  for (int j = 1; j < n - 1; ++j)
177  {
178  nodeList[skips[i][0] + j * skips[i][1]] =
179  m_edgeList[i]->m_edgeNodes[j - 1];
180  }
181  }
182  }
183 
184  // Write interior
185  for (int i = 1; i < n - 1; ++i)
186  {
187  for (int j = 1; j < n - 1; ++j)
188  {
189  nodeList[i * n + j] =
190  m_faceNodes[(i - 1) * (n - 2) + (j - 1)];
191  }
192  }
193  }
194  }
195 
196  /// Generates a string listing the coordinates of all nodes
197  /// associated with this face.
198  std::string GetXmlCurveString() const
199  {
200  std::stringstream s;
201  std::string str;
202  std::vector<NodeSharedPtr> nodeList;
203 
204  // assemble listof nodes
205  GetCurvedNodes(nodeList);
206 
207  // put them into a string
208  for (int k = 0; k < nodeList.size(); ++k)
209  {
210  s << std::scientific << std::setprecision(8) << " "
211  << nodeList[k]->m_x << " " << nodeList[k]->m_y << " "
212  << nodeList[k]->m_z << " ";
213  }
214 
215  return s.str();
216  }
217 
218  /// Generate either SpatialDomains::TriGeom or
219  /// SpatialDomains::QuadGeom for this element.
221  {
222  int nEdge = m_edgeList.size();
223 
226  StdRegions::Orientation edgeo[4];
227 
228  for (int i = 0; i < nEdge; ++i)
229  {
230  edges[i] = m_edgeList[i]->GetGeom(coordDim);
231  }
232 
233  for (int i = 0; i < nEdge; ++i)
234  {
235  edgeo[i] = m_edgeList[i]->m_n1 == m_vertexList[i]
238  }
239 
240  if (m_faceNodes.size() > 0)
241  {
242  if (nEdge == 3)
243  {
246  m_id, m_curveType);
247 
248  for (int j = 0; j < m_vertexList.size(); j++)
249  {
250  c->m_points.push_back(m_vertexList[j]->GetGeom(coordDim));
251  }
252  for (int j = 0; j < nEdge; j++)
253  {
254  std::vector<NodeSharedPtr> ed = m_edgeList[j]->m_edgeNodes;
255  if (edgeo[j] == StdRegions::eBackwards)
256  {
257  for (int k = ed.size() - 1; k >= 0; k--)
258  {
259  c->m_points.push_back(ed[k]->GetGeom(coordDim));
260  }
261  }
262  else
263  {
264  for (int k = 0; k < ed.size(); k++)
265  {
266  c->m_points.push_back(ed[k]->GetGeom(coordDim));
267  }
268  }
269  }
270  for (int j = 0; j < m_faceNodes.size(); j++)
271  {
272  c->m_points.push_back(m_faceNodes[j]->GetGeom(coordDim));
273  }
274 
276  m_id, edges, edgeo, c);
277  }
278  else
279  {
282  m_id, m_curveType);
283 
284  ASSERTL0(m_vertexList.size() == 4,
285  "Face nodes of tensor product only supported "
286  "for quadrilaterals.");
287 
288  int n = (int)sqrt((NekDouble)GetNodeCount());
289  std::vector<NodeSharedPtr> tmp(n * n);
290 
291  ASSERTL0(n * n == GetNodeCount(), "Wrong number of modes?");
292 
293  // Write vertices
294  tmp[0] = m_vertexList[0];
295  tmp[n - 1] = m_vertexList[1];
296  tmp[n * n - 1] = m_vertexList[2];
297  tmp[n * (n - 1)] = m_vertexList[3];
298 
299  // Write edge-interior
300  int skips[4][2] = {
301  {0, 1}, {n - 1, n}, {n * n - 1, -1}, {n * (n - 1), -n}};
302  for (int i = 0; i < 4; ++i)
303  {
304  bool reverseEdge = edgeo[i] == StdRegions::eBackwards;
305 
306  if (reverseEdge)
307  {
308  for (int j = 1; j < n - 1; ++j)
309  {
310  tmp[skips[i][0] + j * skips[i][1]] =
311  m_edgeList[i]->m_edgeNodes[n - 2 - j];
312  }
313  }
314  else
315  {
316  for (int j = 1; j < n - 1; ++j)
317  {
318  tmp[skips[i][0] + j * skips[i][1]] =
319  m_edgeList[i]->m_edgeNodes[j - 1];
320  }
321  }
322  }
323 
324  // Write interior
325  for (int i = 1; i < n - 1; ++i)
326  {
327  for (int j = 1; j < n - 1; ++j)
328  {
329  tmp[i * n + j] =
330  m_faceNodes[(i - 1) * (n - 2) + (j - 1)];
331  }
332  }
333 
334  for (int k = 0; k < tmp.size(); ++k)
335  {
336  c->m_points.push_back(tmp[k]->GetGeom(coordDim));
337  }
338 
339  ret =
341  m_id, edges, edgeo, c);
342  }
343  }
344  else
345  {
346  if (nEdge == 3)
347  {
349  m_id, edges, edgeo);
350  }
351  else
352  {
353  ret =
355  m_id, edges, edgeo);
356  }
357  }
358 
359  return ret;
360  }
361 
362  /// ID of the face.
363  unsigned int m_id;
364  /// List of vertex nodes.
365  std::vector<NodeSharedPtr> m_vertexList;
366  /// List of corresponding edges.
367  std::vector<EdgeSharedPtr> m_edgeList;
368  /// List of face-interior nodes defining the shape of the face.
369  std::vector<NodeSharedPtr> m_faceNodes;
370  /// Distribution of points in this face.
372  /// Element(s) which are linked to this face.
373  std::vector<std::pair<ElementSharedPtr, int> > m_elLink;
374  /// Nektar++ representation of geometry
376 };
377 /// Shared pointer to a face.
378 typedef boost::shared_ptr<Face> FaceSharedPtr;
379 
380 NEKMESHUTILS_EXPORT bool operator==(FaceSharedPtr const &p1,
381  FaceSharedPtr const &p2);
382 NEKMESHUTILS_EXPORT bool operator<(FaceSharedPtr const &p1,
383  FaceSharedPtr const &p2);
384 
385 struct FaceHash : std::unary_function<FaceSharedPtr, std::size_t>
386 {
387  std::size_t operator()(FaceSharedPtr const &p) const
388  {
389  unsigned int nVert = p->m_vertexList.size();
390  std::size_t seed = 0;
391  std::vector<unsigned int> ids(nVert);
392 
393  for (int i = 0; i < nVert; ++i)
394  {
395  ids[i] = p->m_vertexList[i]->m_id;
396  }
397 
398  std::sort(ids.begin(), ids.end());
399  boost::hash_range(seed, ids.begin(), ids.end());
400 
401  return seed;
402  }
403 };
404 typedef boost::unordered_set<FaceSharedPtr, FaceHash> FaceSet;
405 }
406 }
407 
408 #endif
bool operator<(NodeSharedPtr const &p1, NodeSharedPtr const &p2)
Defines ordering between two NodeSharedPtr objects.
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:161
void GetCurvedNodes(std::vector< NodeSharedPtr > &nodeList) const
Assemble a list of nodes on curved face.
Definition: Face.h:114
std::vector< NodeSharedPtr > m_faceNodes
List of face-interior nodes defining the shape of the face.
Definition: Face.h:369
static boost::shared_ptr< DataType > AllocateSharedPtr()
Allocate a shared pointer from the memory pool.
unsigned int GetNodeCount() const
Returns the total number of nodes (vertices, edge nodes and face nodes).
Definition: Face.h:102
Represents a face comprised of three or more edges.
Definition: Face.h:60
std::string GetXmlCurveString() const
Generates a string listing the coordinates of all nodes associated with this face.
Definition: Face.h:198
std::vector< std::pair< ElementSharedPtr, int > > m_elLink
Element(s) which are linked to this face.
Definition: Face.h:373
Face(const Face &pSrc)
Copy an existing face.
Definition: Face.h:74
std::vector< EdgeSharedPtr > m_edgeList
List of corresponding edges.
Definition: Face.h:367
std::size_t operator()(FaceSharedPtr const &p) const
Definition: Face.h:387
unsigned int m_id
ID of the face.
Definition: Face.h:363
bool operator==(Face &pSrc)
Equality is defined by matching all vertices.
Definition: Face.h:85
boost::shared_ptr< Curve > CurveSharedPtr
Definition: Curve.hpp:62
boost::unordered_set< FaceSharedPtr, FaceHash > FaceSet
Definition: Face.h:404
Face(std::vector< NodeSharedPtr > pVertexList, std::vector< NodeSharedPtr > pFaceNodes, std::vector< EdgeSharedPtr > pEdgeList, LibUtilities::PointsType pCurveType)
Create a new face.
Definition: Face.h:64
boost::shared_ptr< SegGeom > SegGeomSharedPtr
Definition: Geometry2D.h:60
LibUtilities::PointsType m_curveType
Distribution of points in this face.
Definition: Face.h:371
double NekDouble
2D Nodal Fekete Points on a Triangle
Definition: PointsType.h:69
boost::shared_ptr< Geometry2D > Geometry2DSharedPtr
Definition: Geometry2D.h:59
SpatialDomains::Geometry2DSharedPtr GetGeom(int coordDim)
Generate either SpatialDomains::TriGeom or SpatialDomains::QuadGeom for this element.
Definition: Face.h:220
StandardMatrixTag boost::call_traits< LhsDataType >::const_reference rhs typedef NekMatrix< LhsDataType, StandardMatrixTag >::iterator iterator
#define NEKMESHUTILS_EXPORT
InputIterator find(InputIterator first, InputIterator last, InputIterator startingpoint, const EqualityComparable &value)
Definition: StdRegions.hpp:315
2D Evenly-spaced points on a Triangle
Definition: PointsType.h:70
boost::shared_ptr< Element > ElementSharedPtr
Definition: Edge.h:52
boost::shared_ptr< Face > FaceSharedPtr
Shared pointer to a face.
Definition: Face.h:378
std::vector< NodeSharedPtr > m_vertexList
List of vertex nodes.
Definition: Face.h:365
2D Nodal Electrostatic Points on a Triangle
Definition: PointsType.h:68
SpatialDomains::Geometry2DSharedPtr m_geom
Nektar++ representation of geometry.
Definition: Face.h:375