Nektar++
TriGeom.cpp
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////////////
2//
3// File: TriGeom.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:
32//
33//
34////////////////////////////////////////////////////////////////////////////////
35
40
43
44using namespace std;
45
46namespace Nektar
47{
48namespace SpatialDomains
49{
50
52{
54}
55
56TriGeom::TriGeom(const int id, const SegGeomSharedPtr edges[],
57 const CurveSharedPtr curve)
58 : Geometry2D(edges[0]->GetVertex(0)->GetCoordim(), curve)
59{
60 int j;
61
63 m_globalID = id;
64
65 // Copy the edge shared pointers.
66 m_edges.insert(m_edges.begin(), edges, edges + TriGeom::kNedges);
67 m_eorient.resize(kNedges);
68
69 for (j = 0; j < kNedges; ++j)
70 {
71 m_eorient[j] =
72 SegGeom::GetEdgeOrientation(*edges[j], *edges[(j + 1) % kNedges]);
73 m_verts.push_back(
74 edges[j]->GetVertex(m_eorient[j] == StdRegions::eForwards ? 0 : 1));
75 }
76
80
81 m_coordim = edges[0]->GetVertex(0)->GetCoordim();
82 ASSERTL0(m_coordim > 1, "Cannot call function with dim == 1");
83}
84
86{
87 // From Geometry
89
90 // From TriFaceComponent
92
93 // From TriGeom
94 m_verts = in.m_verts;
95 m_edges = in.m_edges;
96 for (int i = 0; i < kNedges; i++)
97 {
98 m_eorient[i] = in.m_eorient[i];
99 }
100}
101
103{
104}
105
107 const Array<OneD, const NekDouble> &Lcoord)
108{
109 ASSERTL1(m_state == ePtsFilled, "Geometry is not in physical space");
110
111 Array<OneD, NekDouble> tmp(m_xmap->GetTotPoints());
112 m_xmap->BwdTrans(m_coeffs[i], tmp);
113
114 return m_xmap->PhysEvaluate(Lcoord, tmp);
115}
116
118 const TriGeom &face2,
119 bool doRot, int dir,
120 NekDouble angle,
121 NekDouble tol)
122{
123 return GetFaceOrientation(face1.m_verts, face2.m_verts, doRot, dir, angle,
124 tol);
125}
126
128 const PointGeomVector &face1, const PointGeomVector &face2, bool doRot,
129 int dir, NekDouble angle, NekDouble tol)
130{
131 int i, j, vmap[3] = {-1, -1, -1};
132
133 if (doRot)
134 {
135 PointGeom rotPt;
136
137 for (i = 0; i < 3; ++i)
138 {
139 rotPt.Rotate((*face1[i]), dir, angle);
140 for (j = 0; j < 3; ++j)
141 {
142 if (rotPt.dist(*face2[j]) < tol)
143 {
144 vmap[j] = i;
145 break;
146 }
147 }
148 }
149 }
150 else
151 {
152
153 NekDouble x, y, z, x1, y1, z1, cx = 0.0, cy = 0.0, cz = 0.0;
154
155 // For periodic faces, we calculate the vector between the centre
156 // points of the two faces. (For connected faces this will be
157 // zero). We can then use this to determine alignment later in the
158 // algorithm.
159 for (i = 0; i < 3; ++i)
160 {
161 cx += (*face2[i])(0) - (*face1[i])(0);
162 cy += (*face2[i])(1) - (*face1[i])(1);
163 cz += (*face2[i])(2) - (*face1[i])(2);
164 }
165 cx /= 3;
166 cy /= 3;
167 cz /= 3;
168
169 // Now construct a mapping which takes us from the vertices of one
170 // face to the other. That is, vertex j of face2 corresponds to
171 // vertex vmap[j] of face1.
172 for (i = 0; i < 3; ++i)
173 {
174 x = (*face1[i])(0);
175 y = (*face1[i])(1);
176 z = (*face1[i])(2);
177 for (j = 0; j < 3; ++j)
178 {
179 x1 = (*face2[j])(0) - cx;
180 y1 = (*face2[j])(1) - cy;
181 z1 = (*face2[j])(2) - cz;
182 if (sqrt((x1 - x) * (x1 - x) + (y1 - y) * (y1 - y) +
183 (z1 - z) * (z1 - z)) < 1e-8)
184 {
185 vmap[j] = i;
186 break;
187 }
188 }
189 }
190 }
191
192 if (vmap[1] == (vmap[0] + 1) % 3)
193 {
194 switch (vmap[0])
195 {
196 case 0:
198 break;
199 case 1:
201 break;
202 case 2:
204 break;
205 }
206 }
207 else
208 {
209 switch (vmap[0])
210 {
211 case 0:
213 break;
214 case 1:
216 break;
217 case 2:
219 break;
220 }
221 }
222
223 ASSERTL0(false, "Unable to determine triangle orientation");
225}
226
228{
229 if (!m_setupState)
230 {
232 }
233
235 {
236 GeomType Gtype = eRegular;
237
239
240 // check to see if expansions are linear
241 m_straightEdge = true;
242 if (m_xmap->GetBasisNumModes(0) != 2 ||
243 m_xmap->GetBasisNumModes(1) != 2)
244 {
245 Gtype = eDeformed;
246 m_straightEdge = false;
247 }
248
250 m_manifold[0] = 0;
251 m_manifold[1] = 1;
252 if (m_coordim == 3)
253 {
254 PointGeom e01, e21, norm;
255 e01.Sub(*m_verts[0], *m_verts[1]);
256 e21.Sub(*m_verts[2], *m_verts[1]);
257 norm.Mult(e01, e21);
258 int tmpi = 0;
259 double tmp = std::fabs(norm[0]);
260 if (tmp < fabs(norm[1]))
261 {
262 tmp = fabs(norm[1]);
263 tmpi = 1;
264 }
265 if (tmp < fabs(norm[2]))
266 {
267 tmpi = 2;
268 }
269 m_manifold[0] = (tmpi + 1) % 3;
270 m_manifold[1] = (tmpi + 2) % 3;
271 }
272 if (Gtype == eRegular)
273 {
275 for (int i = 0; i < m_verts.size(); ++i)
276 {
277 verts[i] = Array<OneD, NekDouble>(3);
278 m_verts[i]->GetCoords(verts[i]);
279 }
280 // a00 + a01 xi1 + a02 xi2
281 // a10 + a11 xi1 + a12 xi2
283 for (int i = 0; i < 2; ++i)
284 {
285 unsigned int d = m_manifold[i];
287 NekDouble A = verts[0][d];
288 NekDouble B = verts[1][d];
289 NekDouble C = verts[2][d];
290 m_isoParameter[i][0] = 0.5 * (B + C); // 1
291 m_isoParameter[i][1] = 0.5 * (-A + B); // xi1
292 m_isoParameter[i][2] = 0.5 * (-A + C); // xi2
293 }
295 }
296
298 Gtype, m_coordim, m_xmap, m_coeffs);
299
301 }
302}
303
304/**
305 * Note verts and edges are listed according to anticlockwise
306 * convention but points in _coeffs have to be in array format from
307 * left to right.
308 */
310{
311 // check to see if geometry structure is already filled
312 if (m_state == ePtsFilled)
313 {
314 return;
315 }
316
317 int i, j, k;
318 int nEdgeCoeffs = m_xmap->GetTraceNcoeffs(0);
319
320 if (m_curve)
321 {
323 2, m_curve->m_ptype)]
324 ->GetPointsDim();
325
326 // Deal with 2D points type separately
327 // (e.g. electrostatic or Fekete points) to 1D tensor
328 // product.
329 if (pdim == 2)
330 {
331 int N = m_curve->m_points.size();
332 int nEdgePts =
333 (-1 + (int)sqrt(static_cast<NekDouble>(8 * N + 1))) / 2;
334
335 ASSERTL0(nEdgePts * (nEdgePts + 1) / 2 == N,
336 "NUMPOINTS should be a triangle number for"
337 " triangle curved face " +
338 boost::lexical_cast<string>(m_globalID));
339
340 // Sanity check 1: are curved vertices consistent with
341 // triangle vertices?
342 for (i = 0; i < 3; ++i)
343 {
344 NekDouble dist = m_verts[i]->dist(*(m_curve->m_points[i]));
346 {
347 std::stringstream ss;
348 ss << "Curved vertex " << i << " of triangle " << m_globalID
349 << " is separated from expansion vertex by"
350 << " more than " << NekConstants::kVertexTheSameDouble
351 << " (dist = " << dist << ")";
352 NEKERROR(ErrorUtil::ewarning, ss.str().c_str());
353 }
354 }
355
356 // Sanity check 2: are curved edges from the face curvature
357 // consistent with curved edges?
358 for (i = 0; i < kNedges; ++i)
359 {
360 CurveSharedPtr edgeCurve = m_edges[i]->GetCurve();
361
362 ASSERTL0(edgeCurve->m_points.size() == nEdgePts,
363 "Number of edge points does not correspond "
364 "to number of face points in triangle " +
365 boost::lexical_cast<string>(m_globalID));
366
367 const int offset = 3 + i * (nEdgePts - 2);
368 NekDouble maxDist = 0.0;
369
370 // Account for different ordering of nodal coordinates
371 // vs. Cartesian ordering of element.
373
374 if (i == 2)
375 {
376 orient = orient == StdRegions::eForwards
379 }
380
381 if (orient == StdRegions::eForwards)
382 {
383 for (j = 0; j < nEdgePts - 2; ++j)
384 {
385 NekDouble dist = m_curve->m_points[offset + j]->dist(
386 *(edgeCurve->m_points[j + 1]));
387 maxDist = dist > maxDist ? dist : maxDist;
388 }
389 }
390 else
391 {
392 for (j = 0; j < nEdgePts - 2; ++j)
393 {
394 NekDouble dist = m_curve->m_points[offset + j]->dist(
395 *(edgeCurve->m_points[nEdgePts - 2 - j]));
396 maxDist = dist > maxDist ? dist : maxDist;
397 }
398 }
399
401 {
402 std::stringstream ss;
403 ss << "Curved edge " << i << " of triangle " << m_globalID
404 << " has a point separated from edge interior"
405 << " points by more than "
407 << " (maxdist = " << maxDist << ")";
408 NEKERROR(ErrorUtil::ewarning, ss.str().c_str());
409 }
410 }
411
415 nEdgePts, LibUtilities::eGaussRadauMAlpha1Beta0);
417 P0);
419 P1);
421 max(nEdgePts * nEdgePts, m_xmap->GetTotPoints()));
422 Array<OneD, NekDouble> tmp(nEdgePts * nEdgePts);
423
424 for (i = 0; i < m_coordim; ++i)
425 {
426 // Create a StdNodalTriExp.
429 AllocateSharedPtr(T0, T1, m_curve->m_ptype);
430
431 for (j = 0; j < N; ++j)
432 {
433 phys[j] = (m_curve->m_points[j]->GetPtr())[i];
434 }
435
436 t->BwdTrans(phys, tmp);
437
438 // Interpolate points to standard region.
440 P0, P1, tmp, m_xmap->GetBasis(0)->GetPointsKey(),
441 m_xmap->GetBasis(1)->GetPointsKey(), phys);
442
443 // Forwards transform to get coefficient space.
444 m_xmap->FwdTrans(phys, m_coeffs[i]);
445 }
446 }
447 else if (pdim == 1)
448 {
449 int npts = m_curve->m_points.size();
450 int nEdgePts = (int)sqrt(static_cast<NekDouble>(npts));
451 Array<OneD, NekDouble> tmp(npts);
452 Array<OneD, NekDouble> phys(m_xmap->GetTotPoints());
453 LibUtilities::PointsKey curveKey(nEdgePts, m_curve->m_ptype);
454
455 // Sanity checks:
456 // - Curved faces should have square number of points;
457 // - Each edge should have sqrt(npts) points.
458 ASSERTL0(nEdgePts * nEdgePts == npts,
459 "NUMPOINTS should be a square number for"
460 " triangle " +
461 boost::lexical_cast<string>(m_globalID));
462
463 for (i = 0; i < kNedges; ++i)
464 {
465 ASSERTL0(m_edges[i]->GetXmap()->GetNcoeffs() == nEdgePts,
466 "Number of edge points does not correspond to "
467 "number of face points in triangle " +
468 boost::lexical_cast<string>(m_globalID));
469 }
470
471 for (i = 0; i < m_coordim; ++i)
472 {
473 for (j = 0; j < npts; ++j)
474 {
475 tmp[j] = (m_curve->m_points[j]->GetPtr())[i];
476 }
477
478 // Interpolate curve points to standard triangle
479 // points.
480 LibUtilities::Interp2D(curveKey, curveKey, tmp,
481 m_xmap->GetBasis(0)->GetPointsKey(),
482 m_xmap->GetBasis(1)->GetPointsKey(),
483 phys);
484
485 // Forwards transform to get coefficient space.
486 m_xmap->FwdTrans(phys, m_coeffs[i]);
487 }
488 }
489 else
490 {
491 ASSERTL0(false, "Only 1D/2D points distributions "
492 "supported.");
493 }
494 }
495
496 Array<OneD, unsigned int> mapArray(nEdgeCoeffs);
497 Array<OneD, int> signArray(nEdgeCoeffs);
498
499 for (i = 0; i < kNedges; i++)
500 {
501 m_edges[i]->FillGeom();
502 m_xmap->GetTraceToElementMap(i, mapArray, signArray, m_eorient[i]);
503
504 nEdgeCoeffs = m_edges[i]->GetXmap()->GetNcoeffs();
505
506 for (j = 0; j < m_coordim; j++)
507 {
508 for (k = 0; k < nEdgeCoeffs; k++)
509 {
510 m_coeffs[j][mapArray[k]] =
511 signArray[k] * m_edges[i]->GetCoeffs(j)[k];
512 }
513 }
514 }
515
517}
518
519int TriGeom::v_GetDir(const int i, const int j) const
520{
521 boost::ignore_unused(j); // required in 3D shapes
522
523 return i == 0 ? 0 : 1;
524}
525
526void TriGeom::v_Reset(CurveMap &curvedEdges, CurveMap &curvedFaces)
527{
528 Geometry::v_Reset(curvedEdges, curvedFaces);
529 CurveMap::iterator it = curvedFaces.find(m_globalID);
530
531 if (it != curvedFaces.end())
532 {
533 m_curve = it->second;
534 }
535
536 for (int i = 0; i < 3; ++i)
537 {
538 m_edges[i]->Reset(curvedEdges, curvedFaces);
539 }
540
541 SetUpXmap();
542 SetUpCoeffs(m_xmap->GetNcoeffs());
543}
544
546{
547 if (!m_setupState)
548 {
549 for (int i = 0; i < 3; ++i)
550 {
551 m_edges[i]->Setup();
552 }
553 SetUpXmap();
554 SetUpCoeffs(m_xmap->GetNcoeffs());
555 m_setupState = true;
556 }
557}
558
560{
561 int order0 = m_edges[0]->GetXmap()->GetBasis(0)->GetNumModes();
562 int order1 =
563 max(order0, max(m_edges[1]->GetXmap()->GetBasis(0)->GetNumModes(),
564 m_edges[2]->GetXmap()->GetBasis(0)->GetNumModes()));
565
566 const LibUtilities::BasisKey B0(
568 LibUtilities::PointsKey(order0 + 1,
570 const LibUtilities::BasisKey B1(
572 LibUtilities::PointsKey(order1, LibUtilities::eGaussRadauMAlpha1Beta0));
573
575}
576
577} // namespace SpatialDomains
578} // namespace Nektar
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
Definition: ErrorUtil.hpp:209
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
Definition: ErrorUtil.hpp:249
Describes the specification for a Basis.
Definition: Basis.h:47
Defines a specification for a set of points.
Definition: Points.h:55
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
2D geometry information
Definition: Geometry2D.h:69
Array< OneD, int > m_manifold
Definition: Geometry2D.h:86
std::vector< StdRegions::Orientation > m_eorient
Definition: Geometry2D.h:84
virtual void v_CalculateInverseIsoParam() override
Definition: Geometry2D.cpp:625
bool m_setupState
Wether or not the setup routines have been run.
Definition: Geometry.h:196
PointGeomSharedPtr GetVertex(int i) const
Returns vertex i of this object.
Definition: Geometry.h:358
GeomState m_state
Enumeration to dictate whether coefficients are filled.
Definition: Geometry.h:194
void SetUpCoeffs(const int nCoeffs)
Initialise the Geometry::m_coeffs array.
Definition: Geometry.h:690
Array< OneD, Array< OneD, NekDouble > > m_isoParameter
Definition: Geometry.h:207
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:390
LibUtilities::ShapeType m_shapeType
Type of shape.
Definition: Geometry.h:200
Array< OneD, Array< OneD, NekDouble > > m_coeffs
Array containing expansion coefficients of m_xmap.
Definition: Geometry.h:204
GeomState m_geomFactorsState
State of the geometric factors.
Definition: Geometry.h:190
StdRegions::StdExpansionSharedPtr m_xmap
mapping containing isoparametric transformation.
Definition: Geometry.h:192
StdRegions::StdExpansionSharedPtr GetXmap() const
Return the mapping object Geometry::m_xmap that represents the coordinate transformation from standar...
Definition: Geometry.h:436
GeomFactorsSharedPtr m_geomFactors
Geometric factors.
Definition: Geometry.h:188
int m_coordim
Coordinate dimension of this geometry object.
Definition: Geometry.h:186
void Sub(PointGeom &a, PointGeom &b)
Definition: PointGeom.cpp:124
void Mult(PointGeom &a, PointGeom &b)
_this = a x b
Definition: PointGeom.cpp:133
void Rotate(PointGeom &a, int dir, NekDouble angle)
_this = rotation of a by angle 'angle' around axis dir
Definition: PointGeom.cpp:142
NekDouble dist(PointGeom &a)
return distance between this and input a
Definition: PointGeom.cpp:180
static StdRegions::Orientation GetEdgeOrientation(const SegGeom &edge1, const SegGeom &edge2)
Get the orientation of edge1.
Definition: SegGeom.cpp:196
static const int kNedges
Get the orientation of face1.
Definition: TriGeom.h:72
virtual void v_GenGeomFactors() override
Definition: TriGeom.cpp:227
virtual int v_GetDir(const int faceidx, const int facedir) const override
Returns the element coordinate direction corresponding to a given face coordinate direction.
Definition: TriGeom.cpp:519
static StdRegions::Orientation GetFaceOrientation(const TriGeom &face1, const TriGeom &face2, bool doRot, int dir, NekDouble angle, NekDouble tol)
Definition: TriGeom.cpp:117
virtual void v_FillGeom() override
Definition: TriGeom.cpp:309
virtual NekDouble v_GetCoord(const int i, const Array< OneD, const NekDouble > &Lcoord) override
Given local collapsed coordinate Lcoord, return the value of physical coordinate in direction i.
Definition: TriGeom.cpp:106
virtual void v_Reset(CurveMap &curvedEdges, CurveMap &curvedFaces) override
Reset this geometry object: unset the current state, zero Geometry::m_coeffs and remove allocated Geo...
Definition: TriGeom.cpp:526
virtual void v_Setup() override
Definition: TriGeom.cpp:545
PointsManagerT & PointsManager(void)
void Interp2D(const BasisKey &fbasis0, const BasisKey &fbasis1, const Array< OneD, const NekDouble > &from, const BasisKey &tbasis0, const BasisKey &tbasis1, Array< OneD, NekDouble > &to)
this function interpolates a 2D function evaluated at the quadrature points of the 2D basis,...
Definition: Interp.cpp:103
@ eGaussLobattoLegendre
1D Gauss-Lobatto-Legendre quadrature points
Definition: PointsType.h:53
@ eModified_B
Principle Modified Functions .
Definition: BasisType.h:51
@ eOrtho_A
Principle Orthogonal Functions .
Definition: BasisType.h:44
@ eOrtho_B
Principle Orthogonal Functions .
Definition: BasisType.h:46
@ eModified_A
Principle Modified Functions .
Definition: BasisType.h:50
static const NekDouble kVertexTheSameDouble
std::vector< PointGeomSharedPtr > PointGeomVector
Definition: Geometry2D.h:64
std::shared_ptr< Curve > CurveSharedPtr
Definition: Curve.hpp:60
std::unordered_map< int, CurveSharedPtr > CurveMap
Definition: Curve.hpp:61
GeomType
Indicates the type of element geometry.
@ eRegular
Geometry is straight-sided with constant geometric factors.
@ eDeformed
Geometry is curved or has non-constant factors.
std::shared_ptr< SegGeom > SegGeomSharedPtr
Definition: Geometry2D.h:62
@ ePtsFilled
Geometric information has been generated.
std::shared_ptr< StdNodalTriExp > StdNodalTriExpSharedPtr
std::vector< double > z(NPUPPER)
std::vector< double > d(NPUPPER *NPUPPER)
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
double NekDouble
scalarT< T > sqrt(scalarT< T > in)
Definition: scalar.hpp:294