Nektar++
Face.cpp
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // File: Face.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 // Permission is hereby granted, free of charge, to any person obtaining a
14 // copy of this software and associated documentation files (the "Software"),
15 // to deal in the Software without restriction, including without limitation
16 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 // and/or sell copies of the Software, and to permit persons to whom the
18 // Software is furnished to do so, subject to the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be included
21 // in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 // DEALINGS IN THE SOFTWARE.
30 //
31 // Description: Mesh face object.
32 //
33 ////////////////////////////////////////////////////////////////////////////////
34 
36 
38 
40 
41 namespace Nektar
42 {
43 namespace NekMeshUtils
44 {
45 
47  std::vector<NodeSharedPtr> &nodeList)
48 {
49  // Treat 2D point distributions differently to 3D.
53  {
54  int n = m_edgeList[0]->GetNodeCount();
55  int n2 = m_edgeList[1]->GetNodeCount();
56  int n3 = m_edgeList[2]->GetNodeCount();
57 
58  bool same = (n == n2 ? (n2 == n3) : false);
59  ASSERTL0(same, "Edges are not consistent");
60 
61  nodeList.insert(
62  nodeList.end(), m_vertexList.begin(), m_vertexList.end());
63  for (int k = 0; k < m_edgeList.size(); ++k)
64  {
65  nodeList.insert(nodeList.end(),
66  m_edgeList[k]->m_edgeNodes.begin(),
67  m_edgeList[k]->m_edgeNodes.end());
68  if (m_edgeList[k]->m_n1 != m_vertexList[k])
69  {
70  // If edge orientation is reversed relative to node
71  // ordering, we need to reverse order of nodes.
72  std::reverse(nodeList.begin() + 3 + k * (n - 2),
73  nodeList.begin() + 3 + (k + 1) * (n - 2));
74  }
75  }
76  nodeList.insert(
77  nodeList.end(), m_faceNodes.begin(), m_faceNodes.end());
78  }
79  else
80  {
81  // Write out in 2D tensor product order.
82  ASSERTL0(m_vertexList.size() == 4,
83  "Face nodes of tensor product only supported "
84  "for quadrilaterals.");
85 
86  int n = (int)sqrt((NekDouble)GetNodeCount());
87  nodeList.resize(n * n);
88 
89  ASSERTL0(n * n == GetNodeCount(), "Wrong number of modes?");
90 
91  // Write vertices
92  nodeList[0] = m_vertexList[0];
93  nodeList[n - 1] = m_vertexList[1];
94  nodeList[n * n - 1] = m_vertexList[2];
95  nodeList[n * (n - 1)] = m_vertexList[3];
96 
97  // Write edge-interior
98  int skips[4][2] = {
99  {0, 1}, {n - 1, n}, {n * n - 1, -1}, {n * (n - 1), -n}};
100  for (int i = 0; i < 4; ++i)
101  {
102  bool reverseEdge = m_edgeList[i]->m_n1 == m_vertexList[i];
103 
104  if (!reverseEdge)
105  {
106  for (int j = 1; j < n - 1; ++j)
107  {
108  nodeList[skips[i][0] + j * skips[i][1]] =
109  m_edgeList[i]->m_edgeNodes[n - 2 - j];
110  }
111  }
112  else
113  {
114  for (int j = 1; j < n - 1; ++j)
115  {
116  nodeList[skips[i][0] + j * skips[i][1]] =
117  m_edgeList[i]->m_edgeNodes[j - 1];
118  }
119  }
120  }
121 
122  // Write interior
123  for (int i = 1; i < n - 1; ++i)
124  {
125  for (int j = 1; j < n - 1; ++j)
126  {
127  nodeList[i * n + j] =
128  m_faceNodes[(i - 1) * (n - 2) + (j - 1)];
129  }
130  }
131  }
132 }
133 
134 
136 {
137  std::stringstream s;
138  std::string str;
139  std::vector<NodeSharedPtr> nodeList;
140 
141  // assemble listof nodes
142  GetCurvedNodes(nodeList);
143 
144  // put them into a string
145  for (int k = 0; k < nodeList.size(); ++k)
146  {
147  s << std::scientific << std::setprecision(8) << " "
148  << nodeList[k]->m_x << " " << nodeList[k]->m_y << " "
149  << nodeList[k]->m_z << " ";
150  }
151 
152  return s.str();
153 }
154 
155 void Face::MakeOrder(int order,
158  int coordDim,
159  int &id)
160 {
161  if (m_vertexList.size() == 3)
162  {
163  // Triangles of order < 3 have no interior volume points.
164  if (order < 3)
165  {
166  m_faceNodes.clear();
167  return;
168  }
169 
170  int nPoints = order + 1;
171  StdRegions::StdExpansionSharedPtr xmap = geom->GetXmap();
172 
173  Array<OneD, NekDouble> px, py;
174  LibUtilities::PointsKey pKey(nPoints, pType);
175  ASSERTL1(pKey.GetPointsDim() == 2, "Points distribution must be 2D");
176  LibUtilities::PointsManager()[pKey]->GetPoints(px, py);
177 
178  Array<OneD, Array<OneD, NekDouble> > phys(coordDim);
179 
180  for (int i = 0; i < coordDim; ++i)
181  {
182  phys[i] = Array<OneD, NekDouble>(xmap->GetTotPoints());
183  xmap->BwdTrans(geom->GetCoeffs(i), phys[i]);
184  }
185 
186  const int nTriPts = nPoints * (nPoints + 1) / 2;
187  const int nTriIntPts = (nPoints - 3) * (nPoints - 2) / 2;
188  m_faceNodes.resize(nTriIntPts);
189 
190  for (int i = 3 + 3*(nPoints-2), cnt = 0; i < nTriPts; ++i, ++cnt)
191  {
193  xp[0] = px[i];
194  xp[1] = py[i];
195 
196  Array<OneD, NekDouble> x(3, 0.0);
197  for (int j = 0; j < coordDim; ++j)
198  {
199  x[j] = xmap->PhysEvaluate(xp, phys[j]);
200  }
201 
202  m_faceNodes[cnt] = std::shared_ptr<Node>(
203  new Node(id++, x[0], x[1], x[2]));
204  }
205  m_curveType = pType;
206  }
207  else if (m_vertexList.size() == 4)
208  {
209  // Quads of order < 2 have no interior volume points.
210  if (order < 2)
211  {
212  m_faceNodes.clear();
213  return;
214  }
215 
216  int nPoints = order + 1;
217  StdRegions::StdExpansionSharedPtr xmap = geom->GetXmap();
218 
220  LibUtilities::PointsKey pKey(nPoints, pType);
221  ASSERTL1(pKey.GetPointsDim() == 1, "Points distribution must be 1D");
222  LibUtilities::PointsManager()[pKey]->GetPoints(px);
223 
224  Array<OneD, Array<OneD, NekDouble> > phys(coordDim);
225 
226  for (int i = 0; i < coordDim; ++i)
227  {
228  phys[i] = Array<OneD, NekDouble>(xmap->GetTotPoints());
229  xmap->BwdTrans(geom->GetCoeffs(i), phys[i]);
230  }
231 
232  int nQuadIntPts = (nPoints - 2) * (nPoints - 2);
233  m_faceNodes.resize(nQuadIntPts);
234 
235  for (int i = 1, cnt = 0; i < nPoints-1; ++i)
236  {
237  for (int j = 1; j < nPoints-1; ++j, ++cnt)
238  {
240  xp[0] = px[j];
241  xp[1] = px[i];
242 
243  Array<OneD, NekDouble> x(3, 0.0);
244  for (int k = 0; k < coordDim; ++k)
245  {
246  x[k] = xmap->PhysEvaluate(xp, phys[k]);
247  }
248 
249  m_faceNodes[cnt] = std::shared_ptr<Node>(
250  new Node(id++, x[0], x[1], x[2]));
251  }
252  }
253 
254  m_curveType = pType;
255  }
256  else
257  {
258  ASSERTL0(false, "Unknown number of vertices");
259  }
260 
261  if(m_parentCAD)
262  {
263  CADSurfSharedPtr s = std::dynamic_pointer_cast<CADSurf>(m_parentCAD);
264  for(int i = 0; i < m_faceNodes.size(); i++)
265  {
267  loc[0] = m_faceNodes[i]->m_x;
268  loc[1] = m_faceNodes[i]->m_y;
269  loc[2] = m_faceNodes[i]->m_z;
270  Array<OneD, NekDouble> uv = s->locuv(loc);
271  loc = s->P(uv);
272  m_faceNodes[i]->m_x = loc[0];
273  m_faceNodes[i]->m_y = loc[1];
274  m_faceNodes[i]->m_z = loc[2];
275  m_faceNodes[i]->SetCADSurf(s,uv);
276  }
277  }
278 }
279 
281 {
282  int nEdge = m_edgeList.size();
283 
286  StdRegions::Orientation edgeo[4];
287 
288  for (int i = 0; i < nEdge; ++i)
289  {
290  edges[i] = m_edgeList[i]->GetGeom(coordDim);
291  }
292 
293  for (int i = 0; i < nEdge; ++i)
294  {
295  edgeo[i] = m_edgeList[i]->m_n1 == m_vertexList[i]
298  }
299 
300  if (m_faceNodes.size() > 0)
301  {
302  if (nEdge == 3)
303  {
306  m_id, m_curveType);
307 
308  for (int j = 0; j < m_vertexList.size(); j++)
309  {
310  c->m_points.push_back(m_vertexList[j]->GetGeom(coordDim));
311  }
312  for (int j = 0; j < nEdge; j++)
313  {
314  std::vector<NodeSharedPtr> ed = m_edgeList[j]->m_edgeNodes;
315  if (edgeo[j] == StdRegions::eBackwards)
316  {
317  for (int k = ed.size() - 1; k >= 0; k--)
318  {
319  c->m_points.push_back(ed[k]->GetGeom(coordDim));
320  }
321  }
322  else
323  {
324  for (int k = 0; k < ed.size(); k++)
325  {
326  c->m_points.push_back(ed[k]->GetGeom(coordDim));
327  }
328  }
329  }
330  for (int j = 0; j < m_faceNodes.size(); j++)
331  {
332  c->m_points.push_back(m_faceNodes[j]->GetGeom(coordDim));
333  }
334 
336  m_id, edges, c);
337  }
338  else
339  {
342  m_id, m_curveType);
343 
344  ASSERTL0(m_vertexList.size() == 4,
345  "Face nodes of tensor product only supported "
346  "for quadrilaterals.");
347 
348  int n = (int)sqrt((NekDouble)GetNodeCount());
349  std::vector<NodeSharedPtr> tmp(n * n);
350 
351  ASSERTL0(n * n == GetNodeCount(), "Wrong number of modes?");
352 
353  // Write vertices
354  tmp[0] = m_vertexList[0];
355  tmp[n - 1] = m_vertexList[1];
356  tmp[n * n - 1] = m_vertexList[2];
357  tmp[n * (n - 1)] = m_vertexList[3];
358 
359  // Write edge-interior
360  int skips[4][2] = {
361  {0, 1}, {n - 1, n}, {n * n - 1, -1}, {n * (n - 1), -n}};
362  for (int i = 0; i < 4; ++i)
363  {
364  bool reverseEdge = edgeo[i] == StdRegions::eBackwards;
365 
366  if (reverseEdge)
367  {
368  for (int j = 1; j < n - 1; ++j)
369  {
370  tmp[skips[i][0] + j * skips[i][1]] =
371  m_edgeList[i]->m_edgeNodes[n - 2 - j];
372  }
373  }
374  else
375  {
376  for (int j = 1; j < n - 1; ++j)
377  {
378  tmp[skips[i][0] + j * skips[i][1]] =
379  m_edgeList[i]->m_edgeNodes[j - 1];
380  }
381  }
382  }
383 
384  // Write interior
385  for (int i = 1; i < n - 1; ++i)
386  {
387  for (int j = 1; j < n - 1; ++j)
388  {
389  tmp[i * n + j] =
390  m_faceNodes[(i - 1) * (n - 2) + (j - 1)];
391  }
392  }
393 
394  for (int k = 0; k < tmp.size(); ++k)
395  {
396  c->m_points.push_back(tmp[k]->GetGeom(coordDim));
397  }
398 
399  ret =
401  m_id, edges, c);
402  }
403  }
404  else
405  {
406  if (nEdge == 3)
407  {
409  m_id, edges);
410  }
411  else
412  {
413  ret =
415  m_id, edges);
416  }
417  }
418 
419  ret->Setup();
420  return ret;
421 }
422 
423 }
424 }
std::shared_ptr< CADSurf > CADSurfSharedPtr
Definition: CADCurve.h:51
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
NEKMESHUTILS_EXPORT void GetCurvedNodes(std::vector< NodeSharedPtr > &nodeList)
Assemble a list of nodes on curved face.
Definition: Face.cpp:46
void MakeOrder(int order, SpatialDomains::GeometrySharedPtr geom, LibUtilities::PointsType pType, int coordDim, int &id)
Make this face an order order face.
Definition: Face.cpp:155
std::vector< NodeSharedPtr > m_faceNodes
List of face-interior nodes defining the shape of the face.
Definition: Face.h:144
NEKMESHUTILS_EXPORT unsigned int GetNodeCount() const
Returns the total number of nodes (vertices, edge nodes and face nodes).
Definition: Face.h:107
std::shared_ptr< Geometry2D > Geometry2DSharedPtr
Definition: Geometry.h:65
std::vector< EdgeSharedPtr > m_edgeList
List of corresponding edges.
Definition: Face.h:142
unsigned int GetPointsDim() const
Definition: Points.h:150
unsigned int m_id
ID of the face.
Definition: Face.h:138
std::shared_ptr< StdExpansion > StdExpansionSharedPtr
std::shared_ptr< Geometry > GeometrySharedPtr
Definition: Geometry.h:53
base class for a cad surface
Definition: CADSurf.h:71
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
PointsManagerT & PointsManager(void)
NEKMESHUTILS_EXPORT std::string GetXmlCurveString()
Generates a string listing the coordinates of all nodes associated with this face.
Definition: Face.cpp:135
Defines a specification for a set of points.
Definition: Points.h:59
LibUtilities::PointsType m_curveType
Distribution of points in this face.
Definition: Face.h:146
double NekDouble
2D Nodal Fekete Points on a Triangle
Definition: PointsType.h:70
NEKMESHUTILS_EXPORT SpatialDomains::Geometry2DSharedPtr GetGeom(int coordDim)
Generate either SpatialDomains::TriGeom or SpatialDomains::QuadGeom for this element.
Definition: Face.cpp:280
std::shared_ptr< Curve > CurveSharedPtr
Definition: Curve.hpp:61
2D Evenly-spaced points on a Triangle
Definition: PointsType.h:71
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
Definition: ErrorUtil.hpp:250
std::shared_ptr< SegGeom > SegGeomSharedPtr
Definition: Geometry2D.h:62
CADObjectSharedPtr m_parentCAD
Definition: Face.h:152
std::vector< NodeSharedPtr > m_vertexList
List of vertex nodes.
Definition: Face.h:140
2D Nodal Electrostatic Points on a Triangle
Definition: PointsType.h:69