Nektar++
CurveMesh.cpp
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // File: CurveMesh.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: curvemesh object methods.
32 //
33 ////////////////////////////////////////////////////////////////////////////////
34 
37 
38 using namespace std;
39 namespace Nektar
40 {
41 namespace NekMeshUtils
42 {
43 
44 void CurveMesh::ReMesh()
45 {
46  m_meshpoints.clear();
47  m_dst.clear();
48  m_ps.clear();
49  meshsvalue.clear();
50  for(int i = 0; i < m_meshedges.size(); i++)
51  {
52  m_mesh->m_edgeSet.erase(m_meshedges[i]);
53  }
54  m_meshedges.clear();
55 
56  Mesh(true);
57 }
58 
59 void CurveMesh::Mesh(bool forceThree)
60 {
61  // this algorithm is mostly based on the work in chapter 19
62 
63  m_bounds = m_cadcurve->GetBounds();
64  m_curvelength = m_cadcurve->GetTotLength();
65  m_numSamplePoints =
66  int(m_curvelength / m_mesh->m_octree->GetMinDelta()) + 10;
67  ds = m_curvelength / (m_numSamplePoints - 1);
68 
69  // compute the offset due to adjacent BLs
70  NekDouble totalOffset = 0.0;
71  for (map<unsigned, NekDouble>::iterator ie = m_endoffset.begin();
72  ie != m_endoffset.end(); ++ie)
73  {
74  totalOffset += ie->second;
75  }
76  ASSERTL0(m_curvelength > totalOffset,
77  "Boundary layers too thick for adjacent curve");
78 
79  GetSampleFunction();
80 
81  Ae = 0.0;
82 
83  for (int i = 0; i < m_numSamplePoints - 1; i++)
84  {
85  Ae += ds * (1.0 / m_dst[i][0] + 1.0 / m_dst[i + 1][0]) / 2.0;
86  }
87 
88  Ne = round(Ae);
89 
90  if (Ne + 1 < 2 + m_endoffset.size())
91  {
92  Ne = 1 + m_endoffset.size();
93 
94  meshsvalue.resize(Ne + 1);
95  meshsvalue[0] = 0.0;
96  meshsvalue[1] = m_curvelength;
97 
98  if (m_endoffset.count(0))
99  {
100  meshsvalue[1] = m_endoffset[0];
101  }
102  if (m_endoffset.count(1))
103  {
104  meshsvalue[Ne - 1] = m_curvelength - m_endoffset[1];
105  }
106  }
107  else if(Ne + 1 == 2 && forceThree)
108  {
109  Ne++;
110  meshsvalue.resize(Ne + 1);
111  meshsvalue[0] = 0.0;
112  meshsvalue[1] = m_curvelength/ 2.0;
113  meshsvalue[2] = m_curvelength;
114  }
115  else
116  {
117 
118  GetPhiFunction();
119 
120  meshsvalue.resize(Ne + 1);
121  meshsvalue[0] = 0.0;
122  meshsvalue[Ne] = m_curvelength;
123 
124  // force the second and/or the second to last point(s) if an offset is
125  // defined
126  if (m_endoffset.count(0))
127  {
128  meshsvalue[1] = m_endoffset[0];
129  }
130  if (m_endoffset.count(1))
131  {
132  meshsvalue[Ne - 1] = m_curvelength - m_endoffset[1];
133  }
134 
135  for (int i = 1 + m_endoffset.count(0); i < Ne - m_endoffset.count(1);
136  i++)
137  {
138  int iterationcounter = 0;
139  bool iterate = true;
140  int k = i;
141  NekDouble ski = meshsvalue[i - 1];
142  NekDouble lastSki;
143  while (iterate)
144  {
145  iterationcounter++;
146  NekDouble rhs = EvaluateDS(ski) / Ae * (EvaluatePS(ski) - k);
147  lastSki = ski;
148  ski = ski - rhs;
149  if (abs(lastSki - ski) < 1E-8)
150  {
151  iterate = false;
152  }
153 
154  ASSERTL0(iterationcounter < 1000000, "iteration failed");
155  }
156 
157  meshsvalue[i] = ski;
158  }
159  }
160 
161  NekDouble t;
163 
164  vector<CADVertSharedPtr> verts = m_cadcurve->GetVertex();
165  vector<pair<CADSurfSharedPtr, CADOrientation::Orientation> > s =
166  m_cadcurve->GetAdjSurf();
167 
168  NodeSharedPtr n = verts[0]->GetNode();
169  t = m_bounds[0];
170  n->SetCADCurve(m_cadcurve, t);
171  loc = n->GetLoc();
172  for (int j = 0; j < s.size(); j++)
173  {
174  if (verts[0]->IsDegen() == s[j].first->GetId())
175  {
176  // if the degen has been set for this node the node
177  // already knows its corrected location
178  continue;
179  }
180 
181  Array<OneD, NekDouble> uv = s[j].first->locuv(loc);
182  n->SetCADSurf(s[j].first, uv);
183  }
184  m_meshpoints.push_back(n);
185 
186  for (int i = 1; i < meshsvalue.size() - 1; i++)
187  {
188  t = m_cadcurve->tAtArcLength(meshsvalue[i]);
189  loc = m_cadcurve->P(t);
190  NodeSharedPtr n2 = std::shared_ptr<Node>(
191  new Node(m_mesh->m_numNodes++, loc[0], loc[1], loc[2]));
192  n2->SetCADCurve(m_cadcurve, t);
193  for (int j = 0; j < s.size(); j++)
194  {
195  Array<OneD, NekDouble> uv = s[j].first->locuv(loc);
196  n2->SetCADSurf(s[j].first, uv);
197  }
198  m_meshpoints.push_back(n2);
199  }
200 
201  n = verts[1]->GetNode();
202  t = m_bounds[1];
203  n->SetCADCurve(m_cadcurve, t);
204  loc = n->GetLoc();
205  for (int j = 0; j < s.size(); j++)
206  {
207  if (verts[1]->IsDegen() == s[j].first->GetId())
208  {
209  // if the degen has been set for this node the node
210  // already knows its corrected location
211  continue;
212  }
213 
214  Array<OneD, NekDouble> uv = s[j].first->locuv(loc);
215  n->SetCADSurf(s[j].first, uv);
216  }
217  m_meshpoints.push_back(n);
218 
219  ASSERTL0(Ne + 1 == m_meshpoints.size(),
220  "incorrect number of points in curve mesh");
221 
222  // make edges and add them to the edgeset for the face mesher to use
223  for (int i = 0; i < m_meshpoints.size() - 1; i++)
224  {
225  EdgeSharedPtr e = std::shared_ptr<Edge>(
226  new Edge(m_meshpoints[i], m_meshpoints[i + 1]));
227  e->m_parentCAD = m_cadcurve;
228  m_mesh->m_edgeSet.insert(e);
229  m_meshedges.push_back(e);
230  }
231 
232  if (m_mesh->m_verbose)
233  {
234  cout << "\r "
235  " "
236  " ";
237  cout << scientific << "\r\t\tCurve " << m_id << endl
238  << "\t\t\tLength: " << m_curvelength << endl
239  << "\t\t\tNodes: " << m_meshpoints.size() << endl
240  << "\t\t\tSample points: " << m_numSamplePoints << endl
241  << endl;
242  }
243 }
244 
245 void CurveMesh::GetPhiFunction()
246 {
247  m_ps.resize(m_numSamplePoints);
248  vector<NekDouble> newPhi;
249  newPhi.resize(2);
250 
251  newPhi[0] = 0.0;
252  newPhi[1] = 0.0;
253 
254  m_ps[0] = newPhi;
255 
256  NekDouble runningInt = 0.0;
257 
258  for (int i = 1; i < m_numSamplePoints; i++)
259  {
260  runningInt += (1.0 / m_dst[i - 1][0] + 1.0 / m_dst[i][0]) / 2.0 * ds;
261  newPhi[0] = Ne / Ae * runningInt;
262  newPhi[1] = m_dst[i][1];
263  m_ps[i] = newPhi;
264  }
265 }
266 
267 NekDouble CurveMesh::EvaluateDS(NekDouble s)
268 {
269  int a = 0;
270  int b = 0;
271 
272  ASSERTL1(!(s < 0)&& !(s > m_curvelength), "s out of bounds");
273 
274  if (s == 0)
275  {
276  return m_dst[0][0];
277  }
278  else if (s == m_curvelength)
279  {
280  return m_dst[m_numSamplePoints - 1][0];
281  }
282 
283  for (int i = 0; i < m_numSamplePoints - 1; i++)
284  {
285  if (m_dst[i][1] < s && m_dst[i + 1][1] >= s)
286  {
287  a = i;
288  b = i + 1;
289  break;
290  }
291  }
292 
293  NekDouble s1 = m_dst[a][1];
294  NekDouble s2 = m_dst[b][1];
295  NekDouble d1 = m_dst[a][0];
296  NekDouble d2 = m_dst[b][0];
297 
298  NekDouble m = (d2 - d1) / (s2 - s1);
299  NekDouble c = d2 - m * s2;
300 
301  ASSERTL0(m * s + c == m * s + c, "DS"); // was getting nans here
302 
303  return m * s + c;
304 }
305 
306 NekDouble CurveMesh::EvaluatePS(NekDouble s)
307 {
308  int a = 0;
309  int b = 0;
310 
311  ASSERTL1(!(s < 0) && !(s > m_curvelength), "s out of bounds");
312 
313  if (s == 0)
314  {
315  return m_ps[0][0];
316  }
317  else if (s == m_curvelength)
318  {
319  return m_ps[m_numSamplePoints - 1][0];
320  }
321 
322  for (int i = 0; i < m_numSamplePoints - 1; i++)
323  {
324  if (m_ps[i][1] < s && m_ps[i + 1][1] >= s)
325  {
326  a = i;
327  b = i + 1;
328  break;
329  }
330  }
331 
332  if (a == b)
333  {
334  cout << endl;
335  cout << a << " " << b << endl;
336  cout << s << endl;
337  exit(-1);
338  }
339 
340  NekDouble s1 = m_ps[a][1];
341  NekDouble s2 = m_ps[b][1];
342  NekDouble d1 = m_ps[a][0];
343  NekDouble d2 = m_ps[b][0];
344 
345  NekDouble m = (d2 - d1) / (s2 - s1);
346  NekDouble c = d2 - m * s2;
347 
348  ASSERTL0(m * s + c == m * s + c, "PS");
349 
350  return m * s + c;
351 }
352 
353 void CurveMesh::GetSampleFunction()
354 {
355  m_dst.resize(m_numSamplePoints);
356 
357  vector<NekDouble> dsti;
358  dsti.resize(3);
359 
360  for (int i = 0; i < m_numSamplePoints; i++)
361  {
362  dsti[1] = i * ds;
363  NekDouble t = m_cadcurve->tAtArcLength(dsti[1]);
364 
365  Array<OneD, NekDouble> loc = m_cadcurve->P(t);
366 
367  bool found = false;
368 
369  // if inside the BL, dsti[0] set to the BL thickness, i.e. the offset
370  if (m_endoffset.count(0))
371  {
372  if (dsti[1] < m_endoffset[0])
373  {
374  dsti[0] = m_endoffset[0];
375  found = true;
376  }
377  }
378  if (m_endoffset.count(1) && !found)
379  {
380  if (dsti[1] > m_curvelength - m_endoffset[1])
381  {
382  dsti[0] = m_endoffset[1];
383  found = true;
384  }
385  }
386  // else, dsti[0] is found from the octree
387  if (!found)
388  {
389  dsti[0] = m_mesh->m_octree->Query(loc);
390  }
391 
392  dsti[2] = t;
393 
394  m_dst[i] = dsti;
395  }
396 }
397 
398 void CurveMesh::PeriodicOverwrite(CurveMeshSharedPtr from)
399 {
400  // clear current mesh points and remove edges from edgeset
401  m_meshpoints.clear();
402  for (int i = 0; i < m_meshedges.size(); i++)
403  {
404  m_mesh->m_edgeSet.erase(m_meshedges[i]);
405  }
406  m_meshedges.clear();
407 
408  ///////
409 
410  int tid = from->GetId();
412  m_mesh->m_cad->GetPeriodicTranslationVector(tid, m_id);
413 
414  CADCurveSharedPtr c1 = m_mesh->m_cad->GetCurve(tid);
415 
416  bool reversed = c1->GetOrienationWRT(1) == m_cadcurve->GetOrienationWRT(1);
417 
418  vector<NodeSharedPtr> nodes = from->GetMeshPoints();
419 
420  vector<pair<CADSurfSharedPtr, CADOrientation::Orientation> > surfs =
421  m_cadcurve->GetAdjSurf();
422 
423  for (int i = 1; i < nodes.size() - 1; i++)
424  {
425  Array<OneD, NekDouble> loc = nodes[i]->GetLoc();
427  new Node(m_mesh->m_numNodes++, loc[0] + T[0], loc[1] + T[1], 0.0));
428 
429  for (int j = 0; j < surfs.size(); j++)
430  {
431  Array<OneD, NekDouble> uv = surfs[j].first->locuv(nn->GetLoc());
432  nn->SetCADSurf(surfs[j].first, uv);
433  }
434 
435  NekDouble t;
436  m_cadcurve->loct(nn->GetLoc(), t);
437  nn->SetCADCurve(m_cadcurve, t);
438 
439  m_meshpoints.push_back(nn);
440  }
441 
442  // Reverse internal nodes of the vector if necessary
443  if (reversed)
444  {
445  reverse(m_meshpoints.begin(), m_meshpoints.end());
446  }
447 
448  vector<CADVertSharedPtr> verts = m_cadcurve->GetVertex();
449 
450  m_meshpoints.insert(m_meshpoints.begin(), verts[0]->GetNode());
451  m_meshpoints.push_back(verts[1]->GetNode());
452  // dont need to realign cad for vertices
453 
454  // make edges and add them to the edgeset for the face mesher to use
455  for (int i = 0; i < m_meshpoints.size() - 1; i++)
456  {
457  EdgeSharedPtr e = std::shared_ptr<Edge>(
458  new Edge(m_meshpoints[i], m_meshpoints[i + 1]));
459  e->m_parentCAD = m_cadcurve;
460  m_mesh->m_edgeSet.insert(e);
461  m_meshedges.push_back(e);
462  }
463 }
464 }
465 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
Represents an edge which joins two points.
Definition: Edge.h:58
STL namespace.
std::shared_ptr< Edge > EdgeSharedPtr
Shared pointer to an edge.
Definition: Edge.h:136
std::shared_ptr< Node > NodeSharedPtr
Definition: CADVert.h:49
std::shared_ptr< CADCurve > CADCurveSharedPtr
Definition: CADCurve.h:219
double NekDouble
StandardMatrixTag boost::call_traits< LhsDataType >::const_reference rhs
std::shared_ptr< CurveMesh > CurveMeshSharedPtr
Definition: CurveMesh.h:51
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
Definition: ErrorUtil.hpp:250