Nektar++
HexGeom.cpp
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // File: HexGeom.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: Hexahedral geometry definition.
32 //
33 ////////////////////////////////////////////////////////////////////////////////
34 
35 #include <SpatialDomains/HexGeom.h>
37 #include <StdRegions/StdHexExp.h>
38 #include <SpatialDomains/SegGeom.h>
41 
42 using namespace std;
43 
44 namespace Nektar
45 {
46 namespace SpatialDomains
47 {
48 
49 const unsigned int HexGeom::VertexEdgeConnectivity[8][3] = {
50  {0, 3, 4}, {0, 1, 5}, {1, 2, 6}, {2, 3, 7},
51  {4, 8, 11}, {5, 8, 9}, {6, 9, 10}, {7, 10, 11}};
52 const unsigned int HexGeom::VertexFaceConnectivity[8][3] = {
53  {0, 1, 4}, {0, 1, 2}, {0, 2, 3}, {0, 3, 4},
54  {1, 4, 5}, {1, 2, 5}, {2, 3, 5}, {3, 4, 5}};
55 const unsigned int HexGeom::EdgeFaceConnectivity[12][2] = {
56  {0, 1}, {0, 2}, {0, 3}, {0, 4}, {1, 4}, {1, 2},
57  {2, 3}, {3, 4}, {1, 5}, {2, 5}, {3, 5}, {4, 5}};
58 
59 HexGeom::HexGeom()
60 {
61  m_shapeType = LibUtilities::eHexahedron;
62 }
63 
64 HexGeom::HexGeom(int id, const QuadGeomSharedPtr faces[])
65  : Geometry3D(faces[0]->GetEdge(0)->GetVertex(0)->GetCoordim())
66 {
68  m_globalID = id;
69 
70  /// Copy the face shared pointers
71  m_faces.insert(m_faces.begin(), faces, faces + HexGeom::kNfaces);
72 
73  /// Set up orientation vectors with correct amount of elements.
74  m_eorient.resize(kNedges);
75  m_forient.resize(kNfaces);
76 
81 }
82 
84 {
85 }
86 
88 {
89  if(!m_setupState)
90  {
92  }
93 
95  {
96  int i, f;
97  GeomType Gtype = eRegular;
98 
99  v_FillGeom();
100 
101  // check to see if expansions are linear
102  for (i = 0; i < m_coordim; ++i)
103  {
104  if (m_xmap->GetBasisNumModes(0) != 2 ||
105  m_xmap->GetBasisNumModes(1) != 2 ||
106  m_xmap->GetBasisNumModes(2) != 2)
107  {
108  Gtype = eDeformed;
109  }
110  }
111 
112  // check to see if all faces are parallelograms
113  if (Gtype == eRegular)
114  {
115  const unsigned int faceVerts[kNfaces][QuadGeom::kNverts] = {
116  {0, 1, 2, 3},
117  {0, 1, 5, 4},
118  {1, 2, 6, 5},
119  {3, 2, 6, 7},
120  {0, 3, 7, 4},
121  {4, 5, 6, 7}};
122 
123  for (f = 0; f < kNfaces; f++)
124  {
125  // Ensure each face is a parallelogram? Check this.
126  for (i = 0; i < m_coordim; i++)
127  {
128  if (fabs((*m_verts[faceVerts[f][0]])(i) -
129  (*m_verts[faceVerts[f][1]])(i) +
130  (*m_verts[faceVerts[f][2]])(i) -
131  (*m_verts[faceVerts[f][3]])(i)) >
133  {
134  Gtype = eDeformed;
135  break;
136  }
137  }
138 
139  if (Gtype == eDeformed)
140  {
141  break;
142  }
143  }
144  }
145 
147  Gtype, m_coordim, m_xmap, m_coeffs);
149  }
150 }
151 
153  Array<OneD, NekDouble> &Lcoords)
154 {
155  NekDouble ptdist = 1e6;
156  int i;
157 
158  v_FillGeom();
159 
160  // calculate local coordinate for coord
161  if (GetMetricInfo()->GetGtype() == eRegular)
162  {
163  NekDouble len0 = 0.0;
164  NekDouble len1 = 0.0;
165  NekDouble len2 = 0.0;
166  NekDouble xi0 = 0.0;
167  NekDouble xi1 = 0.0;
168  NekDouble xi2 = 0.0;
169  Array<OneD, NekDouble> pts(m_xmap->GetTotPoints());
170  int nq0, nq1, nq2;
171 
172  // get points;
173  // find end points
174  for (i = 0; i < m_coordim; ++i)
175  {
176  nq0 = m_xmap->GetNumPoints(0);
177  nq1 = m_xmap->GetNumPoints(1);
178  nq2 = m_xmap->GetNumPoints(2);
179 
180  m_xmap->BwdTrans(m_coeffs[i], pts);
181 
182  // use projection to side 1 to determine xi_1 coordinate based on
183  // length
184  len0 += (pts[nq0 - 1] - pts[0]) * (pts[nq0 - 1] - pts[0]);
185  xi0 += (coords[i] - pts[0]) * (pts[nq0 - 1] - pts[0]);
186 
187  // use projection to side 4 to determine xi_2 coordinate based on
188  // length
189  len1 += (pts[nq0 * (nq1 - 1)] - pts[0]) *
190  (pts[nq0 * (nq1 - 1)] - pts[0]);
191  xi1 += (coords[i] - pts[0]) * (pts[nq0 * (nq1 - 1)] - pts[0]);
192 
193  // use projection to side 4 to determine xi_3 coordinate based on
194  // length
195  len2 += (pts[nq0 * nq1 * (nq2 - 1)] - pts[0]) *
196  (pts[nq0 * nq1 * (nq2 - 1)] - pts[0]);
197  xi2 += (coords[i] - pts[0]) * (pts[nq0 * nq1 * (nq2 - 1)] - pts[0]);
198  }
199 
200  Lcoords[0] = 2 * xi0 / len0 - 1.0;
201  Lcoords[1] = 2 * xi1 / len1 - 1.0;
202  Lcoords[2] = 2 * xi2 / len2 - 1.0;
203 
204  // Set ptdist to distance to nearest vertex
205  // Point inside tetrahedron
206  PointGeom r(m_coordim, 0, coords[0], coords[1], coords[2]);
207  for (int i = 0; i < 8; ++i)
208  {
209  ptdist = min(ptdist, r.dist(*m_verts[i]));
210  }
211  }
212  else
213  {
214  // Determine nearest point of coords to values in m_xmap
215  int npts = m_xmap->GetTotPoints();
216  Array<OneD, NekDouble> ptsx(npts), ptsy(npts), ptsz(npts);
217  Array<OneD, NekDouble> tmp1(npts), tmp2(npts);
218 
219  m_xmap->BwdTrans(m_coeffs[0], ptsx);
220  m_xmap->BwdTrans(m_coeffs[1], ptsy);
221  m_xmap->BwdTrans(m_coeffs[2], ptsz);
222 
223  const Array<OneD, const NekDouble> za = m_xmap->GetPoints(0);
224  const Array<OneD, const NekDouble> zb = m_xmap->GetPoints(1);
225  const Array<OneD, const NekDouble> zc = m_xmap->GetPoints(2);
226 
227  // guess the first local coords based on nearest point
228  Vmath::Sadd(npts, -coords[0], ptsx, 1, tmp1, 1);
229  Vmath::Vmul(npts, tmp1, 1, tmp1, 1, tmp1, 1);
230  Vmath::Sadd(npts, -coords[1], ptsy, 1, tmp2, 1);
231  Vmath::Vvtvp(npts, tmp2, 1, tmp2, 1, tmp1, 1, tmp1, 1);
232  Vmath::Sadd(npts, -coords[2], ptsz, 1, tmp2, 1);
233  Vmath::Vvtvp(npts, tmp2, 1, tmp2, 1, tmp1, 1, tmp1, 1);
234 
235  int min_i = Vmath::Imin(npts, tmp1, 1);
236 
237  // distance from coordinate to nearest point for return value.
238  ptdist = sqrt(tmp1[min_i]);
239 
240  // Get Local coordinates
241  int qa = za.num_elements(), qb = zb.num_elements();
242  Lcoords[2] = zc[min_i / (qa * qb)];
243  min_i = min_i % (qa * qb);
244  Lcoords[1] = zb[min_i / qa];
245  Lcoords[0] = za[min_i % qa];
246 
247  // Perform newton iteration to find local coordinates
248  NekDouble resid = 0.0;
249  NewtonIterationForLocCoord(coords, ptsx, ptsy, ptsz, Lcoords, resid);
250  }
251  return ptdist;
252 }
253 
255  Array<OneD, NekDouble> &locCoord,
256  NekDouble tol,
257  NekDouble &resid)
258 {
259  boost::ignore_unused(resid);
260 
261  //Rough check if within twice min/max point
262  if (GetMetricInfo()->GetGtype() != eRegular)
263  {
264  if (!MinMaxCheck(gloCoord))
265  {
266  return false;
267  }
268  }
269 
270  // Convert to the local Cartesian coordinates.
271  resid = GetLocCoords(gloCoord, locCoord);
272 
273  // Check local coordinate is within cartesian bounds.
274  if (locCoord[0] >= -(1 + tol) && locCoord[0] <= 1 + tol &&
275  locCoord[1] >= -(1 + tol) && locCoord[1] <= 1 + tol &&
276  locCoord[2] >= -(1 + tol) && locCoord[2] <= 1 + tol)
277  {
278  return true;
279  }
280 
281  //Clamp local coords
282  ClampLocCoords(locCoord, tol);
283 
284  return false;
285 }
286 
287 int HexGeom::v_GetVertexEdgeMap(const int i, const int j) const
288 {
289  return VertexEdgeConnectivity[i][j];
290 }
291 
292 int HexGeom::v_GetVertexFaceMap(const int i, const int j) const
293 {
294  return VertexFaceConnectivity[i][j];
295 }
296 
297 int HexGeom::v_GetEdgeFaceMap(const int i, const int j) const
298 {
299  return EdgeFaceConnectivity[i][j];
300 }
301 
302 int HexGeom::v_GetDir(const int faceidx, const int facedir) const
303 {
304  if (faceidx == 0 || faceidx == 5)
305  {
306  return facedir;
307  }
308  else if (faceidx == 1 || faceidx == 3)
309  {
310  return 2 * facedir;
311  }
312  else
313  {
314  return 1 + facedir;
315  }
316 }
317 
319 {
320  // find edge 0
321  int i, j;
322  unsigned int check;
323 
324  SegGeomSharedPtr edge;
325 
326  // First set up the 4 bottom edges
327  int f;
328  for (f = 1; f < 5; f++)
329  {
330  check = 0;
331  for (i = 0; i < 4; i++)
332  {
333  for (j = 0; j < 4; j++)
334  {
335  if ((m_faces[0])->GetEid(i) == (m_faces[f])->GetEid(j))
336  {
337  edge = std::dynamic_pointer_cast<SegGeom>(
338  (m_faces[0])->GetEdge(i));
339  m_edges.push_back(edge);
340  check++;
341  }
342  }
343  }
344 
345  if (check < 1)
346  {
347  std::ostringstream errstrm;
348  errstrm << "Connected faces do not share an edge. Faces ";
349  errstrm << (m_faces[0])->GetGlobalID() << ", "
350  << (m_faces[f])->GetGlobalID();
351  ASSERTL0(false, errstrm.str());
352  }
353  else if (check > 1)
354  {
355  std::ostringstream errstrm;
356  errstrm << "Connected faces share more than one edge. Faces ";
357  errstrm << (m_faces[0])->GetGlobalID() << ", "
358  << (m_faces[f])->GetGlobalID();
359  ASSERTL0(false, errstrm.str());
360  }
361  }
362 
363  // Then, set up the 4 vertical edges
364  check = 0;
365  for (i = 0; i < 4; i++)
366  {
367  for (j = 0; j < 4; j++)
368  {
369  if ((m_faces[1])->GetEid(i) == (m_faces[4])->GetEid(j))
370  {
371  edge = std::dynamic_pointer_cast<SegGeom>(
372  (m_faces[1])->GetEdge(i));
373  m_edges.push_back(edge);
374  check++;
375  }
376  }
377  }
378  if (check < 1)
379  {
380  std::ostringstream errstrm;
381  errstrm << "Connected faces do not share an edge. Faces ";
382  errstrm << (m_faces[1])->GetGlobalID() << ", "
383  << (m_faces[4])->GetGlobalID();
384  ASSERTL0(false, errstrm.str());
385  }
386  else if (check > 1)
387  {
388  std::ostringstream errstrm;
389  errstrm << "Connected faces share more than one edge. Faces ";
390  errstrm << (m_faces[1])->GetGlobalID() << ", "
391  << (m_faces[4])->GetGlobalID();
392  ASSERTL0(false, errstrm.str());
393  }
394  for (f = 1; f < 4; f++)
395  {
396  check = 0;
397  for (i = 0; i < 4; i++)
398  {
399  for (j = 0; j < 4; j++)
400  {
401  if ((m_faces[f])->GetEid(i) == (m_faces[f + 1])->GetEid(j))
402  {
403  edge = std::dynamic_pointer_cast<SegGeom>(
404  (m_faces[f])->GetEdge(i));
405  m_edges.push_back(edge);
406  check++;
407  }
408  }
409  }
410 
411  if (check < 1)
412  {
413  std::ostringstream errstrm;
414  errstrm << "Connected faces do not share an edge. Faces ";
415  errstrm << (m_faces[f])->GetGlobalID() << ", "
416  << (m_faces[f + 1])->GetGlobalID();
417  ASSERTL0(false, errstrm.str());
418  }
419  else if (check > 1)
420  {
421  std::ostringstream errstrm;
422  errstrm << "Connected faces share more than one edge. Faces ";
423  errstrm << (m_faces[f])->GetGlobalID() << ", "
424  << (m_faces[f + 1])->GetGlobalID();
425  ASSERTL0(false, errstrm.str());
426  }
427  }
428 
429  // Finally, set up the 4 top vertices
430  for (f = 1; f < 5; f++)
431  {
432  check = 0;
433  for (i = 0; i < 4; i++)
434  {
435  for (j = 0; j < 4; j++)
436  {
437  if ((m_faces[5])->GetEid(i) == (m_faces[f])->GetEid(j))
438  {
439  edge = std::dynamic_pointer_cast<SegGeom>(
440  (m_faces[5])->GetEdge(i));
441  m_edges.push_back(edge);
442  check++;
443  }
444  }
445  }
446 
447  if (check < 1)
448  {
449  std::ostringstream errstrm;
450  errstrm << "Connected faces do not share an edge. Faces ";
451  errstrm << (m_faces[5])->GetGlobalID() << ", "
452  << (m_faces[f])->GetGlobalID();
453  ASSERTL0(false, errstrm.str());
454  }
455  else if (check > 1)
456  {
457  std::ostringstream errstrm;
458  errstrm << "Connected faces share more than one edge. Faces ";
459  errstrm << (m_faces[5])->GetGlobalID() << ", "
460  << (m_faces[f])->GetGlobalID();
461  ASSERTL0(false, errstrm.str());
462  }
463  }
464 }
465 
467 {
468  // Set up the first 2 vertices (i.e. vertex 0,1)
469  if ((m_edges[0]->GetVid(0) == m_edges[1]->GetVid(0)) ||
470  (m_edges[0]->GetVid(0) == m_edges[1]->GetVid(1)))
471  {
472  m_verts.push_back(m_edges[0]->GetVertex(1));
473  m_verts.push_back(m_edges[0]->GetVertex(0));
474  }
475  else if ((m_edges[0]->GetVid(1) == m_edges[1]->GetVid(0)) ||
476  (m_edges[0]->GetVid(1) == m_edges[1]->GetVid(1)))
477  {
478  m_verts.push_back(m_edges[0]->GetVertex(0));
479  m_verts.push_back(m_edges[0]->GetVertex(1));
480  }
481  else
482  {
483  std::ostringstream errstrm;
484  errstrm << "Connected edges do not share a vertex. Edges ";
485  errstrm << m_edges[0]->GetGlobalID() << ", "
486  << m_edges[1]->GetGlobalID();
487  ASSERTL0(false, errstrm.str());
488  }
489 
490  // set up the other bottom vertices (i.e. vertex 2,3)
491  int i;
492  for (i = 1; i < 3; i++)
493  {
494  if (m_edges[i]->GetVid(0) == m_verts[i]->GetGlobalID())
495  {
496  m_verts.push_back(m_edges[i]->GetVertex(1));
497  }
498  else if (m_edges[i]->GetVid(1) == m_verts[i]->GetGlobalID())
499  {
500  m_verts.push_back(m_edges[i]->GetVertex(0));
501  }
502  else
503  {
504  std::ostringstream errstrm;
505  errstrm << "Connected edges do not share a vertex. Edges ";
506  errstrm << m_edges[i]->GetGlobalID() << ", "
507  << m_edges[i - 1]->GetGlobalID();
508  ASSERTL0(false, errstrm.str());
509  }
510  }
511 
512  // set up top vertices
513  // First, set up vertices 4,5
514  if ((m_edges[8]->GetVid(0) == m_edges[9]->GetVid(0)) ||
515  (m_edges[8]->GetVid(0) == m_edges[9]->GetVid(1)))
516  {
517  m_verts.push_back(m_edges[8]->GetVertex(1));
518  m_verts.push_back(m_edges[8]->GetVertex(0));
519  }
520  else if ((m_edges[8]->GetVid(1) == m_edges[9]->GetVid(0)) ||
521  (m_edges[8]->GetVid(1) == m_edges[9]->GetVid(1)))
522  {
523  m_verts.push_back(m_edges[8]->GetVertex(0));
524  m_verts.push_back(m_edges[8]->GetVertex(1));
525  }
526  else
527  {
528  std::ostringstream errstrm;
529  errstrm << "Connected edges do not share a vertex. Edges ";
530  errstrm << m_edges[8]->GetGlobalID() << ", "
531  << m_edges[9]->GetGlobalID();
532  ASSERTL0(false, errstrm.str());
533  }
534 
535  // set up the other top vertices (i.e. vertex 6,7)
536  for (i = 9; i < 11; i++)
537  {
538  if (m_edges[i]->GetVid(0) == m_verts[i - 4]->GetGlobalID())
539  {
540  m_verts.push_back(m_edges[i]->GetVertex(1));
541  }
542  else if (m_edges[i]->GetVid(1) == m_verts[i - 4]->GetGlobalID())
543  {
544  m_verts.push_back(m_edges[i]->GetVertex(0));
545  }
546  else
547  {
548  std::ostringstream errstrm;
549  errstrm << "Connected edges do not share a vertex. Edges ";
550  errstrm << m_edges[i]->GetGlobalID() << ", "
551  << m_edges[i - 1]->GetGlobalID();
552  ASSERTL0(false, errstrm.str());
553  }
554  }
555 }
556 
558 {
559  int f, i;
560 
561  // These arrays represent the vector of the A and B
562  // coordinate of the local elemental coordinate system
563  // where A corresponds with the coordinate direction xi_i
564  // with the lowest index i (for that particular face)
565  // Coordinate 'B' then corresponds to the other local
566  // coordinate (i.e. with the highest index)
567  Array<OneD, NekDouble> elementAaxis(m_coordim);
568  Array<OneD, NekDouble> elementBaxis(m_coordim);
569 
570  // These arrays correspond to the local coordinate
571  // system of the face itself (i.e. the Geometry2D)
572  // faceAaxis correspond to the xi_0 axis
573  // faceBaxis correspond to the xi_1 axis
576 
577  // This is the base vertex of the face (i.e. the Geometry2D)
578  // This corresponds to thevertex with local ID 0 of the
579  // Geometry2D
580  unsigned int baseVertex;
581 
582  // The lenght of the vectors above
583  NekDouble elementAaxis_length;
584  NekDouble elementBaxis_length;
585  NekDouble faceAaxis_length;
586  NekDouble faceBaxis_length;
587 
588  // This 2D array holds the local id's of all the vertices
589  // for every face. For every face, they are ordered in such
590  // a way that the implementation below allows a unified approach
591  // for all faces.
592  const unsigned int faceVerts[kNfaces][QuadGeom::kNverts] = {{0, 1, 2, 3},
593  {0, 1, 5, 4},
594  {1, 2, 6, 5},
595  {3, 2, 6, 7},
596  {0, 3, 7, 4},
597  {4, 5, 6, 7}};
598 
599  NekDouble dotproduct1 = 0.0;
600  NekDouble dotproduct2 = 0.0;
601 
602  unsigned int orientation;
603 
604  // Loop over all the faces to set up the orientation
605  for (f = 0; f < kNqfaces + kNtfaces; f++)
606  {
607  // initialisation
608  elementAaxis_length = 0.0;
609  elementBaxis_length = 0.0;
610  faceAaxis_length = 0.0;
611  faceBaxis_length = 0.0;
612 
613  dotproduct1 = 0.0;
614  dotproduct2 = 0.0;
615 
616  baseVertex = m_faces[f]->GetVid(0);
617 
618  // We are going to construct the vectors representing the A and B axis
619  // of every face. These vectors will be constructed as a
620  // vector-representation
621  // of the edges of the face. However, for both coordinate directions, we
622  // can
623  // represent the vectors by two different edges. That's why we need to
624  // make sure that
625  // we pick the edge to which the baseVertex of the
626  // Geometry2D-representation of the face
627  // belongs...
628  if (baseVertex == m_verts[faceVerts[f][0]]->GetGlobalID())
629  {
630  for (i = 0; i < m_coordim; i++)
631  {
632  elementAaxis[i] = (*m_verts[faceVerts[f][1]])[i] -
633  (*m_verts[faceVerts[f][0]])[i];
634  elementBaxis[i] = (*m_verts[faceVerts[f][3]])[i] -
635  (*m_verts[faceVerts[f][0]])[i];
636  }
637  }
638  else if (baseVertex == m_verts[faceVerts[f][1]]->GetGlobalID())
639  {
640  for (i = 0; i < m_coordim; i++)
641  {
642  elementAaxis[i] = (*m_verts[faceVerts[f][1]])[i] -
643  (*m_verts[faceVerts[f][0]])[i];
644  elementBaxis[i] = (*m_verts[faceVerts[f][2]])[i] -
645  (*m_verts[faceVerts[f][1]])[i];
646  }
647  }
648  else if (baseVertex == m_verts[faceVerts[f][2]]->GetGlobalID())
649  {
650  for (i = 0; i < m_coordim; i++)
651  {
652  elementAaxis[i] = (*m_verts[faceVerts[f][2]])[i] -
653  (*m_verts[faceVerts[f][3]])[i];
654  elementBaxis[i] = (*m_verts[faceVerts[f][2]])[i] -
655  (*m_verts[faceVerts[f][1]])[i];
656  }
657  }
658  else if (baseVertex == m_verts[faceVerts[f][3]]->GetGlobalID())
659  {
660  for (i = 0; i < m_coordim; i++)
661  {
662  elementAaxis[i] = (*m_verts[faceVerts[f][2]])[i] -
663  (*m_verts[faceVerts[f][3]])[i];
664  elementBaxis[i] = (*m_verts[faceVerts[f][3]])[i] -
665  (*m_verts[faceVerts[f][0]])[i];
666  }
667  }
668  else
669  {
670  ASSERTL0(false, "Could not find matching vertex for the face");
671  }
672 
673  // Now, construct the edge-vectors of the local coordinates of
674  // the Geometry2D-representation of the face
675  for (i = 0; i < m_coordim; i++)
676  {
677  faceAaxis[i] =
678  (*m_faces[f]->GetVertex(1))[i] - (*m_faces[f]->GetVertex(0))[i];
679  faceBaxis[i] =
680  (*m_faces[f]->GetVertex(3))[i] - (*m_faces[f]->GetVertex(0))[i];
681 
682  elementAaxis_length += pow(elementAaxis[i], 2);
683  elementBaxis_length += pow(elementBaxis[i], 2);
684  faceAaxis_length += pow(faceAaxis[i], 2);
685  faceBaxis_length += pow(faceBaxis[i], 2);
686  }
687 
688  elementAaxis_length = sqrt(elementAaxis_length);
689  elementBaxis_length = sqrt(elementBaxis_length);
690  faceAaxis_length = sqrt(faceAaxis_length);
691  faceBaxis_length = sqrt(faceBaxis_length);
692 
693  // Calculate the inner product of both the A-axis
694  // (i.e. Elemental A axis and face A axis)
695  for (i = 0; i < m_coordim; i++)
696  {
697  dotproduct1 += elementAaxis[i] * faceAaxis[i];
698  }
699 
700  NekDouble norm = fabs(dotproduct1) / elementAaxis_length / faceAaxis_length;
701  orientation = 0;
702 
703  // if the innerproduct is equal to the (absolute value of the ) products
704  // of the lengths of both vectors, then, the coordinate systems will NOT
705  // be transposed
706  if (fabs(norm - 1.0) < NekConstants::kNekZeroTol)
707  {
708  // if the inner product is negative, both A-axis point
709  // in reverse direction
710  if (dotproduct1 < 0.0)
711  {
712  orientation += 2;
713  }
714 
715  // calculate the inner product of both B-axis
716  for (i = 0; i < m_coordim; i++)
717  {
718  dotproduct2 += elementBaxis[i] * faceBaxis[i];
719  }
720 
721  norm = fabs(dotproduct2) / elementBaxis_length / faceBaxis_length;
722 
723  // check that both these axis are indeed parallel
724  ASSERTL1(fabs(norm - 1.0) < NekConstants::kNekZeroTol,
725  "These vectors should be parallel");
726 
727  // if the inner product is negative, both B-axis point
728  // in reverse direction
729  if (dotproduct2 < 0.0)
730  {
731  orientation++;
732  }
733  }
734  // The coordinate systems are transposed
735  else
736  {
737  orientation = 4;
738 
739  // Calculate the inner product between the elemental A-axis
740  // and the B-axis of the face (which are now the corresponding axis)
741  dotproduct1 = 0.0;
742  for (i = 0; i < m_coordim; i++)
743  {
744  dotproduct1 += elementAaxis[i] * faceBaxis[i];
745  }
746 
747  norm = fabs(dotproduct1) / elementAaxis_length / faceBaxis_length;
748 
749  // check that both these axis are indeed parallel
750  ASSERTL1(fabs(norm - 1.0) < NekConstants::kNekZeroTol,
751  "These vectors should be parallel");
752 
753  // if the result is negative, both axis point in reverse
754  // directions
755  if (dotproduct1 < 0.0)
756  {
757  orientation += 2;
758  }
759 
760  // Do the same for the other two corresponding axis
761  dotproduct2 = 0.0;
762  for (i = 0; i < m_coordim; i++)
763  {
764  dotproduct2 += elementBaxis[i] * faceAaxis[i];
765  }
766 
767  norm = fabs(dotproduct2) / elementBaxis_length / faceAaxis_length;
768 
769  // check that both these axis are indeed parallel
770  ASSERTL1(fabs(norm - 1.0) < NekConstants::kNekZeroTol,
771  "These vectors should be parallel");
772 
773  if (dotproduct2 < 0.0)
774  {
775  orientation++;
776  }
777  }
778 
779  orientation = orientation + 5;
780  // Fill the m_forient array
781  m_forient[f] = (StdRegions::Orientation)orientation;
782  }
783 }
784 
786 {
787 
788  // This 2D array holds the local id's of all the vertices
789  // for every edge. For every edge, they are ordered to what we
790  // define as being Forwards
791  const unsigned int edgeVerts[kNedges][2] = {{0, 1},
792  {1, 2},
793  {2, 3},
794  {3, 0},
795  {0, 4},
796  {1, 5},
797  {2, 6},
798  {3, 7},
799  {4, 5},
800  {5, 6},
801  {6, 7},
802  {7, 4}};
803 
804  int i;
805  for (i = 0; i < kNedges; i++)
806  {
807  if (m_edges[i]->GetVid(0) == m_verts[edgeVerts[i][0]]->GetGlobalID())
808  {
810  }
811  else if (m_edges[i]->GetVid(0) == m_verts[edgeVerts[i][1]]->GetGlobalID())
812  {
814  }
815  else
816  {
817  ASSERTL0(false, "Could not find matching vertex for the edge");
818  }
819  }
820 }
821 
822 void HexGeom::v_Reset(CurveMap &curvedEdges, CurveMap &curvedFaces)
823 {
824  Geometry::v_Reset(curvedEdges, curvedFaces);
825 
826  for (int i = 0; i < 6; ++i)
827  {
828  m_faces[i]->Reset(curvedEdges, curvedFaces);
829  }
830 
831  SetUpXmap();
832  SetUpCoeffs(m_xmap->GetNcoeffs());
833 }
834 
836 {
837  if(!m_setupState)
838  {
839  for (int i = 0; i < 6; ++i)
840  {
841  m_faces[i]->Setup();
842  }
843  SetUpXmap();
844  SetUpCoeffs(m_xmap->GetNcoeffs());
845  m_setupState = true;
846  }
847 }
848 
849 /**
850  * @brief Set up the #m_xmap object by determining the order of each
851  * direction from derived faces.
852  */
854 {
855  // Determine necessary order for standard region. This can almost certainly
856  // be simplified but works for now!
857  vector<int> tmp1;
858 
859  if (m_forient[0] < 9)
860  {
861  tmp1.push_back(m_faces[0]->GetXmap()->GetEdgeNcoeffs(0));
862  tmp1.push_back(m_faces[0]->GetXmap()->GetEdgeNcoeffs(2));
863  }
864  else
865  {
866  tmp1.push_back(m_faces[0]->GetXmap()->GetEdgeNcoeffs(1));
867  tmp1.push_back(m_faces[0]->GetXmap()->GetEdgeNcoeffs(3));
868  }
869 
870  if (m_forient[5] < 9)
871  {
872  tmp1.push_back(m_faces[5]->GetXmap()->GetEdgeNcoeffs(0));
873  tmp1.push_back(m_faces[5]->GetXmap()->GetEdgeNcoeffs(2));
874  }
875  else
876  {
877  tmp1.push_back(m_faces[5]->GetXmap()->GetEdgeNcoeffs(1));
878  tmp1.push_back(m_faces[5]->GetXmap()->GetEdgeNcoeffs(3));
879  }
880 
881  int order0 = *max_element(tmp1.begin(), tmp1.end());
882 
883  tmp1.clear();
884 
885  if (m_forient[0] < 9)
886  {
887  tmp1.push_back(m_faces[0]->GetXmap()->GetEdgeNcoeffs(1));
888  tmp1.push_back(m_faces[0]->GetXmap()->GetEdgeNcoeffs(3));
889  }
890  else
891  {
892  tmp1.push_back(m_faces[0]->GetXmap()->GetEdgeNcoeffs(0));
893  tmp1.push_back(m_faces[0]->GetXmap()->GetEdgeNcoeffs(2));
894  }
895 
896  if (m_forient[5] < 9)
897  {
898  tmp1.push_back(m_faces[5]->GetXmap()->GetEdgeNcoeffs(1));
899  tmp1.push_back(m_faces[5]->GetXmap()->GetEdgeNcoeffs(3));
900  }
901  else
902  {
903  tmp1.push_back(m_faces[5]->GetXmap()->GetEdgeNcoeffs(0));
904  tmp1.push_back(m_faces[5]->GetXmap()->GetEdgeNcoeffs(2));
905  }
906 
907  int order1 = *max_element(tmp1.begin(), tmp1.end());
908 
909  tmp1.clear();
910 
911  if (m_forient[1] < 9)
912  {
913  tmp1.push_back(m_faces[1]->GetXmap()->GetEdgeNcoeffs(1));
914  tmp1.push_back(m_faces[1]->GetXmap()->GetEdgeNcoeffs(3));
915  }
916  else
917  {
918  tmp1.push_back(m_faces[1]->GetXmap()->GetEdgeNcoeffs(0));
919  tmp1.push_back(m_faces[1]->GetXmap()->GetEdgeNcoeffs(2));
920  }
921 
922  if (m_forient[3] < 9)
923  {
924  tmp1.push_back(m_faces[3]->GetXmap()->GetEdgeNcoeffs(1));
925  tmp1.push_back(m_faces[3]->GetXmap()->GetEdgeNcoeffs(3));
926  }
927  else
928  {
929  tmp1.push_back(m_faces[3]->GetXmap()->GetEdgeNcoeffs(0));
930  tmp1.push_back(m_faces[3]->GetXmap()->GetEdgeNcoeffs(2));
931  }
932 
933  int order2 = *max_element(tmp1.begin(), tmp1.end());
934 
937  order0,
939  const LibUtilities::BasisKey B(
941  order1,
943  const LibUtilities::BasisKey C(
945  order2,
947 
949 }
950 
951 }
952 }
static const unsigned int VertexEdgeConnectivity[8][3]
Definition: HexGeom.h:85
StdRegions::StdExpansionSharedPtr m_xmap
mapping containing isoparametric transformation.
Definition: Geometry.h:189
void SetUpXmap()
Set up the m_xmap object by determining the order of each direction from derived faces.
Definition: HexGeom.cpp:853
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
std::vector< StdRegions::Orientation > m_eorient
Definition: Geometry3D.h:86
int GetEid(int i) const
Get the ID of edge i of this object.
Definition: Geometry.cpp:145
virtual void v_GenGeomFactors()
Definition: HexGeom.cpp:87
GeomFactorsSharedPtr m_geomFactors
Geometric factors.
Definition: Geometry.h:185
StdRegions::StdExpansionSharedPtr GetXmap() const
Return the mapping object Geometry::m_xmap that represents the coordinate transformation from standar...
Definition: Geometry.h:421
std::unordered_map< int, CurveSharedPtr > CurveMap
Definition: Curve.hpp:62
static const int kNtfaces
Definition: HexGeom.h:59
bool MinMaxCheck(const Array< OneD, const NekDouble > &gloCoord)
Check if given global coord is within twice the min/max distance of the element.
Definition: Geometry.cpp:435
std::shared_ptr< QuadGeom > QuadGeomSharedPtr
Definition: HexGeom.h:46
virtual int v_GetEdgeFaceMap(const int i, const int j) const
Returns the standard element edge IDs that are connected to a given face.
Definition: HexGeom.cpp:297
int Imin(int n, const T *x, const int incx)
Return the index of the minimum element in x.
Definition: Vmath.cpp:850
static const int kNverts
Definition: QuadGeom.h:77
void Vvtvp(int n, const T *w, const int incw, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
vvtvp (vector times vector plus vector): z = w*x + y
Definition: Vmath.cpp:445
Principle Modified Functions .
Definition: BasisType.h:48
STL namespace.
virtual void v_Reset(CurveMap &curvedEdges, CurveMap &curvedFaces)
Reset this geometry object: unset the current state, zero Geometry::m_coeffs and remove allocated Geo...
Definition: Geometry.cpp:335
static const int kNfaces
Definition: HexGeom.h:60
void ClampLocCoords(Array< OneD, NekDouble > &locCoord, NekDouble tol)
Clamp local coords to be within standard regions [-1, 1]^dim.
Definition: Geometry.cpp:478
GeomState m_geomFactorsState
State of the geometric factors.
Definition: Geometry.h:187
int GetGlobalID(void) const
Get the ID of this object.
Definition: Geometry.h:314
std::vector< StdRegions::Orientation > m_forient
Definition: Geometry3D.h:87
void NewtonIterationForLocCoord(const Array< OneD, const NekDouble > &coords, const Array< OneD, const NekDouble > &ptsx, const Array< OneD, const NekDouble > &ptsy, const Array< OneD, const NekDouble > &ptsz, Array< OneD, NekDouble > &Lcoords, NekDouble &resid)
Definition: Geometry3D.cpp:81
static const NekDouble kNekZeroTol
virtual NekDouble v_GetLocCoords(const Array< OneD, const NekDouble > &coords, Array< OneD, NekDouble > &Lcoords)
Determine the local collapsed coordinates that correspond to a given Cartesian coordinate for this ge...
Definition: HexGeom.cpp:152
virtual bool v_ContainsPoint(const Array< OneD, const NekDouble > &gloCoord, Array< OneD, NekDouble > &locCoord, NekDouble tol, NekDouble &resid)
Definition: HexGeom.cpp:254
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
virtual void v_Reset(CurveMap &curvedEdges, CurveMap &curvedFaces)
Reset this geometry object: unset the current state, zero Geometry::m_coeffs and remove allocated Geo...
Definition: HexGeom.cpp:822
virtual int v_GetVertexFaceMap(const int i, const int j) const
Returns the standard element face IDs that are connected to a given vertex.
Definition: HexGeom.cpp:292
Defines a specification for a set of points.
Definition: Points.h:59
double NekDouble
bool m_setupState
Wether or not the setup routines have been run.
Definition: Geometry.h:193
int GetVid(int i) const
Get the ID of vertex i of this object.
Definition: Geometry.cpp:137
void Sadd(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Add vector y = alpha + x.
Definition: Vmath.cpp:318
virtual void v_FillGeom()
Put all quadrature information into face/edge structure and backward transform.
Definition: Geometry3D.cpp:235
3D geometry information
Definition: Geometry3D.h:67
Array< OneD, Array< OneD, NekDouble > > m_coeffs
Array containing expansion coefficients of m_xmap.
Definition: Geometry.h:201
static const unsigned int EdgeFaceConnectivity[12][2]
Definition: HexGeom.h:87
Geometry is straight-sided with constant geometric factors.
NekDouble GetLocCoords(const Array< OneD, const NekDouble > &coords, Array< OneD, NekDouble > &Lcoords)
Determine the local collapsed coordinates that correspond to a given Cartesian coordinate for this ge...
Definition: Geometry.h:534
Geometry1DSharedPtr GetEdge(int i) const
Returns edge i of this object.
Definition: Geometry.h:351
LibUtilities::ShapeType m_shapeType
Type of shape.
Definition: Geometry.h:197
static const unsigned int VertexFaceConnectivity[8][3]
Definition: HexGeom.h:86
NekDouble dist(PointGeom &a)
return distance between this and input a
Definition: PointGeom.cpp:181
Geometric information has been generated.
void SetUpCoeffs(const int nCoeffs)
Initialise the Geometry::m_coeffs array.
Definition: Geometry.h:643
static const int kNqfaces
Definition: HexGeom.h:58
GeomFactorsSharedPtr GetMetricInfo()
Get the geometric factors for this object.
Definition: Geometry.h:298
virtual int v_GetDir(const int faceidx, const int facedir) const
Definition: HexGeom.cpp:302
GeomType
Indicates the type of element geometry.
#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
static const int kNedges
Definition: HexGeom.h:57
Geometry is curved or has non-constant factors.
virtual int v_GetVertexEdgeMap(const int i, const int j) const
Returns the standard element edge IDs that are connected to a given vertex.
Definition: HexGeom.cpp:287
PointGeomSharedPtr GetVertex(int i) const
Returns vertex i of this object.
Definition: Geometry.h:343
int m_coordim
Coordinate dimension of this geometry object.
Definition: Geometry.h:183
Describes the specification for a Basis.
Definition: Basis.h:49
1D Gauss-Lobatto-Legendre quadrature points
Definition: PointsType.h:51
void Vmul(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Multiply vector z = x*y.
Definition: Vmath.cpp:186