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