Nektar++
Loading...
Searching...
No Matches
Public Member Functions | Static Public Attributes | Protected Member Functions | Protected Attributes | List of all members
Nektar::SpatialDomains::Geometry2D Class Reference

2D geometry information More...

#include <Geometry2D.h>

Inheritance diagram for Nektar::SpatialDomains::Geometry2D:
[legend]

Public Member Functions

 Geometry2D ()
 
 Geometry2D (const int coordim, Curve *curve)
 
 ~Geometry2D () override=default
 
CurveGetCurve ()
 
void SetCurve (Curve *curvePtr)
 
- Public Member Functions inherited from Nektar::SpatialDomains::Geometry
 Geometry ()
 Default constructor.
 
 Geometry (int coordim)
 Constructor when supplied a coordinate dimension.
 
virtual ~Geometry ()=default
 
int GetCoordim () const
 Return the coordinate dimension of this object (i.e. the dimension of the space in which this object is embedded).
 
void SetCoordim (int coordim)
 Sets the coordinate dimension of this object (i.e. the dimension of the space in which this object is embedded).
 
GeomFactorsUniquePtr GenGeomFactors (LibUtilities::PointsKeyVector &keyTgt)
 Used by Expansion to generate associated GeomFactors.
 
LibUtilities::ShapeType GetShapeType (void)
 Get the geometric shape type of this object.
 
int GetGlobalID (void) const
 Get the ID of this object.
 
void SetGlobalID (int globalid)
 Set the ID of this object.
 
int GetVid (int i) const
 Returns global id of vertex i of this object.
 
int GetEid (int i) const
 Get the ID of edge i of this object.
 
int GetFid (int i) const
 Get the ID of face i of this object.
 
int GetTid (int i) const
 Get the ID of trace i of this object.
 
PointGeomGetVertex (int i) const
 Returns vertex i of this object.
 
Geometry1DGetEdge (int i) const
 Returns edge i of this object.
 
Geometry2DGetFace (int i) const
 Returns face i of this object.
 
StdRegions::Orientation GetEorient (const int i) const
 Returns the orientation of edge i with respect to the ordering of edges in the standard element.
 
StdRegions::Orientation GetForient (const int i) const
 Returns the orientation of face i with respect to the ordering of faces in the standard element.
 
int GetNumVerts () const
 Get the number of vertices of this object.
 
int GetNumEdges () const
 Get the number of edges of this object.
 
int GetNumFaces () const
 Get the number of faces of this object.
 
int GetShapeDim () const
 Get the object's shape dimension.
 
StdRegions::StdExpansionSharedPtr GetXmap () const
 Return the mapping object Geometry::m_xmap that represents the coordinate transformation from standard element to physical element.
 
const Array< OneD, const NekDouble > & GetCoeffs (const int i) const
 Return the coefficients of the transformation Geometry::m_xmap in coordinate direction i.
 
void FillGeom ()
 Populate the coordinate mapping Geometry::m_coeffs information from any children geometry elements.
 
std::array< NekDouble, 6 > GetBoundingBox ()
 Generates the bounding box for the element.
 
void ClearBoundingBox ()
 
bool ContainsPoint (const Array< OneD, const NekDouble > &gloCoord, NekDouble tol=0.0)
 Determine whether an element contains a particular Cartesian coordinate \((x,y,z)\).
 
bool ContainsPoint (const Array< OneD, const NekDouble > &gloCoord, Array< OneD, NekDouble > &locCoord, NekDouble tol)
 Determine whether an element contains a particular Cartesian coordinate \((x,y,z)\).
 
bool ContainsPoint (const Array< OneD, const NekDouble > &gloCoord, Array< OneD, NekDouble > &locCoord, NekDouble tol, NekDouble &dist)
 Determine whether an element contains a particular Cartesian coordinate \(\vec{x} = (x,y,z)\).
 
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 geometry object.
 
NekDouble GetCoord (const int i, const Array< OneD, const NekDouble > &Lcoord)
 Given local collapsed coordinate Lcoord, return the value of physical coordinate in direction i.
 
int PreliminaryCheck (const Array< OneD, const NekDouble > &gloCoord)
 A fast and robust check if a given global coord is outside of a deformed element. For regular elements, this check is unnecessary.
 
bool MinMaxCheck (const Array< OneD, const NekDouble > &gloCoord)
 Check if given global coord is within the BoundingBox of the element.
 
bool ClampLocCoords (Array< OneD, NekDouble > &locCoord, NekDouble tol=std::numeric_limits< NekDouble >::epsilon())
 Clamp local coords to be within standard regions [-1, 1]^dim.
 
NekDouble FindDistance (const Array< OneD, const NekDouble > &xs, Array< OneD, NekDouble > &xi)
 
int GetVertexEdgeMap (int i, int j) const
 Returns the standard element edge IDs that are connected to a given vertex.
 
int GetVertexFaceMap (int i, int j) const
 Returns the standard element face IDs that are connected to a given vertex.
 
int GetEdgeFaceMap (int i, int j) const
 Returns the standard element edge IDs that are connected to a given face.
 
int GetEdgeNormalToFaceVert (int i, int j) const
 Returns the standard lement edge IDs that are normal to a given face vertex.
 
int GetDir (const int i, const int j=0) const
 Returns the element coordinate direction corresponding to a given face coordinate direction.
 
GeomType CalcGeomType ()
 
void Reset (CurveMap &curvedEdges, CurveMap &curvedFaces)
 Reset this geometry object: unset the current state, zero Geometry::m_coeffs and remove allocated GeomFactors.
 
void ResetNonRecursive (CurveMap &curvedEdges, CurveMap &curvedFaces)
 Reset this geometry object non-recursively: unset the current state, zero Geometry::m_coeffs and remove allocated GeomFactors.
 
void Setup ()
 

Static Public Attributes

static const int kDim = 2
 

Protected Member Functions

NekDouble v_GetLocCoords (const Array< OneD, const NekDouble > &coords, Array< OneD, NekDouble > &Lcoords) override
 Determine the local collapsed coordinates that correspond to a given Cartesian coordinate for this geometry object.
 
void NewtonIterationForLocCoord (const Array< OneD, const NekDouble > &coords, const Array< OneD, const NekDouble > &ptsx, const Array< OneD, const NekDouble > &ptsy, Array< OneD, NekDouble > &Lcoords, NekDouble &dist)
 
void SolveStraightEdgeQuad (const Array< OneD, const NekDouble > &coords, Array< OneD, NekDouble > &Lcoords)
 
void v_CalculateInverseIsoParam () override
 
int v_GetShapeDim () const override
 Get the object's shape dimension.
 
NekDouble v_FindDistance (const Array< OneD, const NekDouble > &xs, Array< OneD, NekDouble > &xi) override
 
- Protected Member Functions inherited from Nektar::SpatialDomains::Geometry
virtual int v_GetVid (int i) const
 Get the ID of vertex i of this object.
 
virtual PointGeomv_GetVertex (const int i) const
 Returns vertex i of this object.
 
virtual Geometry1Dv_GetEdge (const int i) const
 Returns edge i of this object.
 
virtual Geometry2Dv_GetFace (const int i) const
 Returns face i of this object.
 
virtual StdRegions::Orientation v_GetEorient (const int i) const
 Returns the orientation of edge i with respect to the ordering of edges in the standard element.
 
virtual StdRegions::Orientation v_GetForient (const int i) const
 Returns the orientation of face i with respect to the ordering of faces in the standard element.
 
virtual int v_GetNumVerts () const
 Get the number of vertices of this object.
 
virtual int v_GetNumEdges () const
 Get the number of edges of this object.
 
virtual int v_GetNumFaces () const
 Get the number of faces of this object.
 
virtual GeomFactorsUniquePtr v_GenGeomFactors (LibUtilities::PointsKeyVector &keyTgt)
 Used by Expansion to generate associated GeomFactors.
 
virtual StdRegions::StdExpansionSharedPtr v_GetXmap () const
 Return the mapping object Geometry::m_xmap that represents the coordinate transformation from standard element to physical element.
 
virtual void v_FillGeom ()
 Populate the coordinate mapping Geometry::m_coeffs information from any children geometry elements.
 
virtual bool v_ContainsPoint (const Array< OneD, const NekDouble > &gloCoord, Array< OneD, NekDouble > &locCoord, NekDouble tol, NekDouble &dist)
 Determine whether an element contains a particular Cartesian coordinate \(\vec{x} = (x,y,z)\).
 
virtual int v_AllLeftCheck (const Array< OneD, const NekDouble > &gloCoord)
 
virtual NekDouble v_GetCoord (const int i, const Array< OneD, const NekDouble > &Lcoord)
 Given local collapsed coordinate Lcoord, return the value of physical coordinate in direction i.
 
virtual int v_GetVertexEdgeMap (int i, int j) const
 Returns the standard element edge IDs that are connected to a given vertex.
 
virtual int v_GetVertexFaceMap (int i, int j) const
 Returns the standard element face IDs that are connected to a given vertex.
 
virtual int v_GetEdgeFaceMap (int i, int j) const
 Returns the standard element edge IDs that are connected to a given face.
 
virtual int v_GetEdgeNormalToFaceVert (const int i, const int j) const
 Returns the standard lement edge IDs that are normal to a given face vertex.
 
virtual int v_GetDir (const int faceidx, const int facedir) const
 Returns the element coordinate direction corresponding to a given face coordinate direction.
 
virtual GeomType v_CalcGeomType ()
 
virtual void v_Reset (CurveMap &curvedEdges, CurveMap &curvedFaces)
 Reset this geometry object: unset the current state, zero Geometry::m_coeffs and remove allocated GeomFactors.
 
virtual void v_Setup ()
 
void SetUpCoeffs (const int nCoeffs)
 Initialise the Geometry::m_coeffs array.
 

Protected Attributes

Curvem_curve
 
Array< OneD, int > m_manifold
 
Array< OneD, Array< OneD, NekDouble > > m_edgeNormal
 
- Protected Attributes inherited from Nektar::SpatialDomains::Geometry
int m_coordim
 Coordinate dimension of this geometry object.
 
StdRegions::StdExpansionSharedPtr m_xmap
 \(\chi\) mapping containing isoparametric transformation.
 
GeomState m_state
 Enumeration to dictate whether coefficients are filled.
 
bool m_setupState
 Wether or not the setup routines have been run.
 
LibUtilities::ShapeType m_shapeType
 Type of shape.
 
int m_globalID
 Global ID.
 
std::vector< Array< OneD, NekDouble > > m_coeffs
 Array containing expansion coefficients of m_xmap.
 
Array< OneD, NekDoublem_boundingBox
 Array containing bounding box.
 
Array< OneD, Array< OneD, NekDouble > > m_isoParameter
 
Array< OneD, Array< OneD, NekDouble > > m_invIsoParam
 
int m_straightEdge
 

Detailed Description

2D geometry information

Definition at line 49 of file Geometry2D.h.

Constructor & Destructor Documentation

◆ Geometry2D() [1/2]

Nektar::SpatialDomains::Geometry2D::Geometry2D ( )

Definition at line 46 of file Geometry2D.cpp.

47{
48}

◆ Geometry2D() [2/2]

Nektar::SpatialDomains::Geometry2D::Geometry2D ( const int  coordim,
Curve curve 
)

Definition at line 50 of file Geometry2D.cpp.

51 : Geometry(coordim), m_curve(curve)
52{
54 "Coordinate dimension should be at least 2 for a 2D geometry");
55}
#define ASSERTL0(condition, msg)
Geometry()
Default constructor.
Definition Geometry.cpp:47
int m_coordim
Coordinate dimension of this geometry object.
Definition Geometry.h:184

References ASSERTL0, and Nektar::SpatialDomains::Geometry::m_coordim.

◆ ~Geometry2D()

Nektar::SpatialDomains::Geometry2D::~Geometry2D ( )
overridedefault

Member Function Documentation

◆ GetCurve()

Curve * Nektar::SpatialDomains::Geometry2D::GetCurve ( )
inline

Definition at line 57 of file Geometry2D.h.

58 {
59 return m_curve;
60 }

References m_curve.

Referenced by export_GeomElements(), and Nektar::SpatialDomains::ZoneBase::ZoneBase().

◆ NewtonIterationForLocCoord()

void Nektar::SpatialDomains::Geometry2D::NewtonIterationForLocCoord ( const Array< OneD, const NekDouble > &  coords,
const Array< OneD, const NekDouble > &  ptsx,
const Array< OneD, const NekDouble > &  ptsy,
Array< OneD, NekDouble > &  Lcoords,
NekDouble dist 
)
protected

Definition at line 84 of file Geometry2D.cpp.

89{
90 // Maximum iterations for convergence
91 const int MaxIterations = NekConstants::kNewtonIterations;
92 // |x-xp|^2 < EPSILON error tolerance
93 const NekDouble Tol = 1.e-8;
94 // |r,s| > LcoordDIV stop the search
95 const NekDouble LcoordDiv = 15.0;
96
97 LibUtilities::PointsKeyVector ptsKeys = m_xmap->GetPointsKeys();
98 Array<OneD, const NekDouble> Jac = v_GenGeomFactors(ptsKeys)->GetJac();
99
100 NekDouble ScaledTol =
101 Vmath::Vsum(Jac.size(), Jac, 1) / ((NekDouble)Jac.size());
102 ScaledTol *= Tol;
103
104 NekDouble xmap, ymap, F1, F2;
105 NekDouble derx_1, derx_2, dery_1, dery_2, jac;
106
107 // save intiial guess for later reference if required.
108 NekDouble init0 = Lcoords[0], init1 = Lcoords[1];
109
110 Array<OneD, NekDouble> DxD1(ptsx.size());
111 Array<OneD, NekDouble> DxD2(ptsx.size());
112 Array<OneD, NekDouble> DyD1(ptsx.size());
113 Array<OneD, NekDouble> DyD2(ptsx.size());
114
115 // Ideally this will be stored in m_geomfactors
116 m_xmap->PhysDeriv(ptsx, DxD1, DxD2);
117 m_xmap->PhysDeriv(ptsy, DyD1, DyD2);
118
119 int cnt = 0;
120 Array<OneD, DNekMatSharedPtr> I(2);
121 Array<OneD, NekDouble> eta(2);
122
123 F1 = F2 = 2000; // Starting value of Function
124 NekDouble resid = sqrt(F1 * F1 + F2 * F2);
125 while (cnt++ < MaxIterations)
126 {
127 // evaluate lagrange interpolant at Lcoords
128 m_xmap->LocCoordToLocCollapsed(Lcoords, eta);
129 I[0] = m_xmap->GetBasis(0)->GetI(eta);
130 I[1] = m_xmap->GetBasis(1)->GetI(eta + 1);
131
132 // calculate the global point `corresponding to Lcoords
133 xmap = m_xmap->PhysEvaluate(I, ptsx);
134 ymap = m_xmap->PhysEvaluate(I, ptsy);
135
136 F1 = coords[0] - xmap;
137 F2 = coords[1] - ymap;
138
139 if (F1 * F1 + F2 * F2 < ScaledTol)
140 {
141 resid = sqrt(F1 * F1 + F2 * F2);
142 break;
143 }
144
145 // Interpolate derivative metric at Lcoords
146 derx_1 = m_xmap->PhysEvaluate(I, DxD1);
147 derx_2 = m_xmap->PhysEvaluate(I, DxD2);
148 dery_1 = m_xmap->PhysEvaluate(I, DyD1);
149 dery_2 = m_xmap->PhysEvaluate(I, DyD2);
150
151 jac = dery_2 * derx_1 - dery_1 * derx_2;
152
153 // use analytical inverse of derivitives which are
154 // also similar to those of metric factors.
155 Lcoords[0] =
156 Lcoords[0] +
157 (dery_2 * (coords[0] - xmap) - derx_2 * (coords[1] - ymap)) / jac;
158
159 Lcoords[1] =
160 Lcoords[1] +
161 (-dery_1 * (coords[0] - xmap) + derx_1 * (coords[1] - ymap)) / jac;
162
163 if (!(std::isfinite(Lcoords[0]) && std::isfinite(Lcoords[1])))
164 {
165 dist = 1e16;
166 std::ostringstream ss;
167 ss << "nan or inf found in NewtonIterationForLocCoord in element "
168 << GetGlobalID();
169 WARNINGL1(false, ss.str());
170 return;
171 }
172 if (fabs(Lcoords[0]) > LcoordDiv || fabs(Lcoords[1]) > LcoordDiv)
173 {
174 break; // lcoords have diverged so stop iteration
175 }
176 }
177
178 m_xmap->LocCoordToLocCollapsed(Lcoords, eta);
179 if (ClampLocCoords(eta, 0.))
180 {
181 I[0] = m_xmap->GetBasis(0)->GetI(eta);
182 I[1] = m_xmap->GetBasis(1)->GetI(eta + 1);
183 // calculate the global point corresponding to Lcoords
184 xmap = m_xmap->PhysEvaluate(I, ptsx);
185 ymap = m_xmap->PhysEvaluate(I, ptsy);
186 F1 = coords[0] - xmap;
187 F2 = coords[1] - ymap;
188 dist = sqrt(F1 * F1 + F2 * F2);
189 }
190 else
191 {
192 dist = 0.;
193 }
194
195 if (cnt >= MaxIterations)
196 {
197 Array<OneD, NekDouble> collCoords(2);
198 m_xmap->LocCoordToLocCollapsed(Lcoords, collCoords);
199
200 // if coordinate is inside element dump error!
201 if ((collCoords[0] >= -1.0 && collCoords[0] <= 1.0) &&
202 (collCoords[1] >= -1.0 && collCoords[1] <= 1.0))
203 {
204 std::ostringstream ss;
205
206 ss << "Reached MaxIterations (" << MaxIterations
207 << ") in Newton iteration ";
208 ss << "Init value (" << std::setprecision(4) << init0 << ","
209 << init1 << ","
210 << ") ";
211 ss << "Fin value (" << Lcoords[0] << "," << Lcoords[1] << ","
212 << ") ";
213 ss << "Resid = " << resid
214 << " Tolerance = " << std::sqrt(ScaledTol);
215
216 WARNINGL1(cnt < MaxIterations, ss.str());
217 }
218 }
219}
#define WARNINGL1(condition, msg)
bool ClampLocCoords(Array< OneD, NekDouble > &locCoord, NekDouble tol=std::numeric_limits< NekDouble >::epsilon())
Clamp local coords to be within standard regions [-1, 1]^dim.
Definition Geometry.cpp:525
int GetGlobalID(void) const
Get the ID of this object.
Definition Geometry.h:314
StdRegions::StdExpansionSharedPtr m_xmap
mapping containing isoparametric transformation.
Definition Geometry.h:186
virtual GeomFactorsUniquePtr v_GenGeomFactors(LibUtilities::PointsKeyVector &keyTgt)
Used by Expansion to generate associated GeomFactors.
Definition Geometry.cpp:197
std::vector< PointsKey > PointsKeyVector
Definition Points.h:313
static const unsigned int kNewtonIterations
T Vsum(int n, const T *x, const int incx)
Subtract return sum(x)
Definition Vmath.hpp:608
scalarT< T > sqrt(scalarT< T > in)
Definition scalar.hpp:290

References Nektar::SpatialDomains::Geometry::ClampLocCoords(), Nektar::SpatialDomains::Geometry::GetGlobalID(), Nektar::NekConstants::kNewtonIterations, Nektar::SpatialDomains::Geometry::m_xmap, tinysimd::sqrt(), Nektar::SpatialDomains::Geometry::v_GenGeomFactors(), Vmath::Vsum(), and WARNINGL1.

Referenced by v_GetLocCoords().

◆ SetCurve()

void Nektar::SpatialDomains::Geometry2D::SetCurve ( Curve curvePtr)
inline

Definition at line 61 of file Geometry2D.h.

62 {
63 m_curve = curvePtr;
64 }

References m_curve.

◆ SolveStraightEdgeQuad()

void Nektar::SpatialDomains::Geometry2D::SolveStraightEdgeQuad ( const Array< OneD, const NekDouble > &  coords,
Array< OneD, NekDouble > &  Lcoords 
)
protected

Definition at line 57 of file Geometry2D.cpp.

59{
60 int i0 = 0, i1 = 1, j1 = 0, j2 = 1;
61 if (m_straightEdge & 2)
62 {
63 i0 = 1;
64 i1 = 0;
65 }
66 if (m_straightEdge & 4)
67 {
68 j1 = 1;
69 j2 = 0;
70 }
72 NekDouble gamma = m_isoParameter[1][3];
73 NekDouble tty = (coords[i1] - gamma * coords[i0] - m_isoParameter[1][0]) *
74 m_isoParameter[1][1];
75 NekDouble denom = 1. / (m_isoParameter[0][2] + m_isoParameter[0][3] * tty);
76 NekDouble epsilon = -m_isoParameter[0][3] * beta * denom;
77 NekDouble h =
78 (m_isoParameter[0][0] + m_isoParameter[0][1] * tty - coords[i0]) *
79 denom;
80 Lcoords[j2] = -h / (0.5 + sqrt(0.25 - epsilon * h));
81 Lcoords[j1] = -beta * Lcoords[j2] + tty;
82}
Array< OneD, Array< OneD, NekDouble > > m_isoParameter
Definition Geometry.h:199
@ beta
Gauss Radau pinned at x=-1,.
Definition PointsType.h:59

References Nektar::LibUtilities::beta, Nektar::SpatialDomains::Geometry::m_isoParameter, Nektar::SpatialDomains::Geometry::m_straightEdge, and tinysimd::sqrt().

Referenced by v_GetLocCoords().

◆ v_CalculateInverseIsoParam()

void Nektar::SpatialDomains::Geometry2D::v_CalculateInverseIsoParam ( )
overrideprotectedvirtual

Reimplemented from Nektar::SpatialDomains::Geometry.

Definition at line 517 of file Geometry2D.cpp.

518{
519 NekDouble Jac = m_isoParameter[0][1] * m_isoParameter[1][2] -
520 m_isoParameter[1][1] * m_isoParameter[0][2];
521 Jac = 1. / Jac;
522 // a12, -a02, -a11, a01
523 m_invIsoParam = Array<OneD, Array<OneD, NekDouble>>(2);
524 m_invIsoParam[0] = Array<OneD, NekDouble>(2);
525 m_invIsoParam[1] = Array<OneD, NekDouble>(2);
526 m_invIsoParam[0][0] = m_isoParameter[1][2] * Jac;
527 m_invIsoParam[0][1] = -m_isoParameter[0][2] * Jac;
528 m_invIsoParam[1][0] = -m_isoParameter[1][1] * Jac;
529 m_invIsoParam[1][1] = m_isoParameter[0][1] * Jac;
530}
Array< OneD, Array< OneD, NekDouble > > m_invIsoParam
Definition Geometry.h:200

References Nektar::SpatialDomains::Geometry::m_invIsoParam, and Nektar::SpatialDomains::Geometry::m_isoParameter.

Referenced by Nektar::SpatialDomains::QuadGeom::v_CalcGeomType(), and Nektar::SpatialDomains::TriGeom::v_CalcGeomType().

◆ v_FindDistance()

NekDouble Nektar::SpatialDomains::Geometry2D::v_FindDistance ( const Array< OneD, const NekDouble > &  xs,
Array< OneD, NekDouble > &  xi 
)
overrideprotectedvirtual

Reimplemented from Nektar::SpatialDomains::Geometry.

Definition at line 290 of file Geometry2D.cpp.

292{
293 GeomType Gtype = CalcGeomType();
294 if (Gtype == eRegular)
295 {
296 xiOut = Array<OneD, NekDouble>(2, 0.0);
297
298 GetLocCoords(xs, xiOut);
299 ClampLocCoords(xiOut);
300
301 Array<OneD, NekDouble> gloCoord(3);
302 gloCoord[0] = GetCoord(0, xiOut);
303 gloCoord[1] = GetCoord(1, xiOut);
304 gloCoord[2] = GetCoord(2, xiOut);
305
306 return sqrt((xs[0] - gloCoord[0]) * (xs[0] - gloCoord[0]) +
307 (xs[1] - gloCoord[1]) * (xs[1] - gloCoord[1]) +
308 (xs[2] - gloCoord[2]) * (xs[2] - gloCoord[2]));
309 }
310 // If deformed edge then the inverse mapping is non-linear so need to
311 // numerically solve for the local coordinate
312 else if (Gtype == eDeformed)
313 {
314 // Choose starting based on closest quad
315 Array<OneD, NekDouble> xi(2, 0.0), eta(2, 0.0);
316 m_xmap->LocCollapsedToLocCoord(eta, xi);
317
318 // Armijo constants:
319 // https://en.wikipedia.org/wiki/Backtracking_line_search
320 const NekDouble c1 = 1e-4, c2 = 0.9;
321
322 int nq = m_xmap->GetTotPoints();
323
324 Array<OneD, NekDouble> x(nq), y(nq), z(nq);
325 m_xmap->BwdTrans(m_coeffs[0], x);
326 m_xmap->BwdTrans(m_coeffs[1], y);
327 m_xmap->BwdTrans(m_coeffs[2], z);
328
329 Array<OneD, NekDouble> xderxi1(nq, 0.0), yderxi1(nq, 0.0),
330 zderxi1(nq, 0.0), xderxi2(nq, 0.0), yderxi2(nq, 0.0),
331 zderxi2(nq, 0.0), xderxi1xi1(nq, 0.0), yderxi1xi1(nq, 0.0),
332 zderxi1xi1(nq, 0.0), xderxi1xi2(nq, 0.0), yderxi1xi2(nq, 0.0),
333 zderxi1xi2(nq, 0.0), xderxi2xi1(nq, 0.0), yderxi2xi1(nq, 0.0),
334 zderxi2xi1(nq, 0.0), xderxi2xi2(nq, 0.0), yderxi2xi2(nq, 0.0),
335 zderxi2xi2(nq, 0.0);
336
337 // Get first & second derivatives & partial derivatives of x,y,z values
338 std::array<NekDouble, 3> xc_derxi, yc_derxi, zc_derxi;
339
340 m_xmap->PhysDeriv(x, xderxi1, xderxi2);
341 m_xmap->PhysDeriv(y, yderxi1, yderxi2);
342 m_xmap->PhysDeriv(z, zderxi1, zderxi2);
343
344 m_xmap->PhysDeriv(xderxi1, xderxi1xi1, xderxi1xi2);
345 m_xmap->PhysDeriv(yderxi1, yderxi1xi1, yderxi1xi2);
346 m_xmap->PhysDeriv(zderxi1, zderxi1xi1, zderxi1xi2);
347
348 m_xmap->PhysDeriv(yderxi2, yderxi2xi1, yderxi2xi2);
349 m_xmap->PhysDeriv(xderxi2, xderxi2xi1, xderxi2xi2);
350 m_xmap->PhysDeriv(zderxi2, zderxi2xi1, zderxi2xi2);
351
352 // Minimisation loop (Quasi-newton method)
353 NekDouble fx_prev = std::numeric_limits<NekDouble>::max();
354 for (int i = 0; i < NekConstants::kNewtonIterations; ++i)
355 {
356 // Compute the objective function, f(x_k) and its derivatives
357 NekDouble xc = m_xmap->PhysEvaluate(xi, x, xc_derxi);
358 NekDouble yc = m_xmap->PhysEvaluate(xi, y, yc_derxi);
359 NekDouble zc = m_xmap->PhysEvaluate(xi, z, zc_derxi);
360
361 NekDouble xc_derxi1xi1 = m_xmap->PhysEvaluate(xi, xderxi1xi1);
362 NekDouble yc_derxi1xi1 = m_xmap->PhysEvaluate(xi, yderxi1xi1);
363 NekDouble zc_derxi1xi1 = m_xmap->PhysEvaluate(xi, zderxi1xi1);
364
365 NekDouble xc_derxi1xi2 = m_xmap->PhysEvaluate(xi, xderxi1xi2);
366 NekDouble yc_derxi1xi2 = m_xmap->PhysEvaluate(xi, yderxi1xi2);
367 NekDouble zc_derxi1xi2 = m_xmap->PhysEvaluate(xi, zderxi1xi2);
368
369 NekDouble xc_derxi2xi2 = m_xmap->PhysEvaluate(xi, xderxi2xi2);
370 NekDouble yc_derxi2xi2 = m_xmap->PhysEvaluate(xi, yderxi2xi2);
371 NekDouble zc_derxi2xi2 = m_xmap->PhysEvaluate(xi, zderxi2xi2);
372
373 // Objective function is the distance to the search point
374 NekDouble xdiff = xc - xs[0];
375 NekDouble ydiff = yc - xs[1];
376 NekDouble zdiff = zc - xs[2];
377
378 NekDouble fx = xdiff * xdiff + ydiff * ydiff + zdiff * zdiff;
379
380 NekDouble fx_derxi1 = 2.0 * xdiff * xc_derxi[0] +
381 2.0 * ydiff * yc_derxi[0] +
382 2.0 * zdiff * zc_derxi[0];
383
384 NekDouble fx_derxi2 = 2.0 * xdiff * xc_derxi[1] +
385 2.0 * ydiff * yc_derxi[1] +
386 2.0 * zdiff * zc_derxi[1];
387
388 NekDouble fx_derxi1xi1 =
389 2.0 * xdiff * xc_derxi1xi1 + 2.0 * xc_derxi[0] * xc_derxi[0] +
390 2.0 * ydiff * yc_derxi1xi1 + 2.0 * yc_derxi[0] * yc_derxi[0] +
391 2.0 * zdiff * zc_derxi1xi1 + 2.0 * zc_derxi[0] * zc_derxi[0];
392
393 NekDouble fx_derxi1xi2 =
394 2.0 * xdiff * xc_derxi1xi2 + 2.0 * xc_derxi[1] * xc_derxi[0] +
395 2.0 * ydiff * yc_derxi1xi2 + 2.0 * yc_derxi[1] * yc_derxi[0] +
396 2.0 * zdiff * zc_derxi1xi2 + 2.0 * zc_derxi[1] * zc_derxi[0];
397
398 NekDouble fx_derxi2xi2 =
399 2.0 * xdiff * xc_derxi2xi2 + 2.0 * xc_derxi[1] * xc_derxi[1] +
400 2.0 * ydiff * yc_derxi2xi2 + 2.0 * yc_derxi[1] * yc_derxi[1] +
401 2.0 * zdiff * zc_derxi2xi2 + 2.0 * zc_derxi[1] * zc_derxi[1];
402
403 // Jacobian
404 NekDouble jac[2];
405 jac[0] = fx_derxi1;
406 jac[1] = fx_derxi2;
407
408 // Inverse of 2x2 hessian
409 NekDouble hessInv[2][2];
410
411 NekDouble det =
412 1 / (fx_derxi1xi1 * fx_derxi2xi2 - fx_derxi1xi2 * fx_derxi1xi2);
413 hessInv[0][0] = det * fx_derxi2xi2;
414 hessInv[0][1] = det * -fx_derxi1xi2;
415 hessInv[1][0] = det * -fx_derxi1xi2;
416 hessInv[1][1] = det * fx_derxi1xi1;
417
418 // Check for convergence
419 if (abs(fx - fx_prev) < 1e-12)
420 {
421 fx_prev = fx;
422 break;
423 }
424 else
425 {
426 fx_prev = fx;
427 }
428
429 NekDouble gamma = 1.0;
430 bool conv = false;
431
432 // Search direction: Newton's method
433 NekDouble pk[2];
434 pk[0] = -(hessInv[0][0] * jac[0] + hessInv[1][0] * jac[1]);
435 pk[1] = -(hessInv[0][1] * jac[0] + hessInv[1][1] * jac[1]);
436
437 // Backtracking line search
438 while (gamma > 1e-10)
439 {
440 Array<OneD, NekDouble> xi_pk(2);
441 xi_pk[0] = xi[0] + pk[0] * gamma;
442 xi_pk[1] = xi[1] + pk[1] * gamma;
443
444 Array<OneD, NekDouble> eta_pk(2, 0.0);
445 m_xmap->LocCoordToLocCollapsed(xi_pk, eta_pk);
446
447 if (eta_pk[0] <
448 (-1 - std::numeric_limits<NekDouble>::epsilon()) ||
449 eta_pk[0] >
450 (1 + std::numeric_limits<NekDouble>::epsilon()) ||
451 eta_pk[1] <
452 (-1 - std::numeric_limits<NekDouble>::epsilon()) ||
453 eta_pk[1] > (1 + std::numeric_limits<NekDouble>::epsilon()))
454 {
455 gamma /= 2.0;
456 continue;
457 }
458
459 std::array<NekDouble, 3> xc_pk_derxi, yc_pk_derxi, zc_pk_derxi;
460
461 NekDouble xc_pk = m_xmap->PhysEvaluate(xi_pk, x, xc_pk_derxi);
462 NekDouble yc_pk = m_xmap->PhysEvaluate(xi_pk, y, yc_pk_derxi);
463 NekDouble zc_pk = m_xmap->PhysEvaluate(xi_pk, z, zc_pk_derxi);
464
465 NekDouble xc_pk_diff = xc_pk - xs[0];
466 NekDouble yc_pk_diff = yc_pk - xs[1];
467 NekDouble zc_pk_diff = zc_pk - xs[2];
468
469 NekDouble fx_pk = xc_pk_diff * xc_pk_diff +
470 yc_pk_diff * yc_pk_diff +
471 zc_pk_diff * zc_pk_diff;
472
473 NekDouble fx_pk_derxi1 = 2.0 * xc_pk_diff * xc_pk_derxi[0] +
474 2.0 * yc_pk_diff * yc_pk_derxi[0] +
475 2.0 * zc_pk_diff * zc_pk_derxi[0];
476
477 NekDouble fx_pk_derxi2 = 2.0 * xc_pk_diff * xc_pk_derxi[1] +
478 2.0 * yc_pk_diff * yc_pk_derxi[1] +
479 2.0 * zc_pk_diff * zc_pk_derxi[1];
480
481 // Check Wolfe conditions using Armijo constants
482 // https://en.wikipedia.org/wiki/Wolfe_conditions
483 NekDouble tmp = pk[0] * fx_derxi1 + pk[1] * fx_derxi2;
484 NekDouble tmp2 = pk[0] * fx_pk_derxi1 + pk[1] * fx_pk_derxi2;
485 if ((fx_pk - (fx + c1 * gamma * tmp)) <
486 std::numeric_limits<NekDouble>::epsilon() &&
487 (-tmp2 - (-c2 * tmp)) <
488 std::numeric_limits<NekDouble>::epsilon())
489 {
490 conv = true;
491 break;
492 }
493
494 gamma /= 2.0;
495 }
496
497 if (!conv)
498 {
499 break;
500 }
501
502 xi[0] += gamma * pk[0];
503 xi[1] += gamma * pk[1];
504 }
505
506 xiOut = xi;
507 return sqrt(fx_prev);
508 }
509 else
510 {
511 NEKERROR(ErrorUtil::efatal, "Geometry type unknown");
512 }
513
514 return -1.0;
515}
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
NekDouble GetCoord(const int i, const Array< OneD, const NekDouble > &Lcoord)
Given local collapsed coordinate Lcoord, return the value of physical coordinate in direction i.
Definition Geometry.h:559
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:549
std::vector< Array< OneD, NekDouble > > m_coeffs
Array containing expansion coefficients of m_xmap.
Definition Geometry.h:196
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::vector< double > z(NPUPPER)
scalarT< T > abs(scalarT< T > in)
Definition scalar.hpp:295

References tinysimd::abs(), Nektar::SpatialDomains::Geometry::CalcGeomType(), Nektar::SpatialDomains::Geometry::ClampLocCoords(), Nektar::SpatialDomains::eDeformed, Nektar::ErrorUtil::efatal, Nektar::SpatialDomains::eRegular, Nektar::SpatialDomains::Geometry::GetCoord(), Nektar::SpatialDomains::Geometry::GetLocCoords(), Nektar::NekConstants::kNewtonIterations, Nektar::SpatialDomains::Geometry::m_coeffs, Nektar::SpatialDomains::Geometry::m_xmap, NEKERROR, and tinysimd::sqrt().

◆ v_GetLocCoords()

NekDouble Nektar::SpatialDomains::Geometry2D::v_GetLocCoords ( const Array< OneD, const NekDouble > &  coords,
Array< OneD, NekDouble > &  Lcoords 
)
overrideprotectedvirtual

Determine the local collapsed coordinates that correspond to a given Cartesian coordinate for this geometry object.

For curvilinear and non-affine elements (i.e. where the Jacobian varies as a function of the standard element coordinates), this is a non-linear optimisation problem that requires the use of a Newton iteration. Note therefore that this can be an expensive operation.

Note that, clearly, the provided Cartesian coordinate lie outside the element. The function therefore returns the minimum distance from some position in the element to . Lcoords will also be constrained to fit within the range \([-1,1]^d\) where \( d \) is the dimension of the element.

Parameters
coordsInput Cartesian global coordinates
LcoordsCorresponding local coordinates
Returns
Distance between obtained coordinates and provided ones.

Reimplemented from Nektar::SpatialDomains::Geometry.

Definition at line 221 of file Geometry2D.cpp.

223{
224 NekDouble dist = std::numeric_limits<double>::max();
225 Array<OneD, NekDouble> tmpcoords(2);
226 tmpcoords[0] = coords[m_manifold[0]];
227 tmpcoords[1] = coords[m_manifold[1]];
228 GeomType Gtype = CalcGeomType();
229 if (Gtype == eRegular)
230 {
231 tmpcoords[0] -= m_isoParameter[0][0];
232 tmpcoords[1] -= m_isoParameter[1][0];
233 Lcoords[0] = m_invIsoParam[0][0] * tmpcoords[0] +
234 m_invIsoParam[0][1] * tmpcoords[1];
235 Lcoords[1] = m_invIsoParam[1][0] * tmpcoords[0] +
236 m_invIsoParam[1][1] * tmpcoords[1];
237 }
238 else if (m_straightEdge)
239 {
240 SolveStraightEdgeQuad(tmpcoords, Lcoords);
241 }
242 else if (Gtype == eDeformed)
243 {
244 v_FillGeom();
245 // Determine nearest point of coords to values in m_xmap
246 int npts = m_xmap->GetTotPoints();
247 Array<OneD, NekDouble> ptsx(npts), ptsy(npts);
248 Array<OneD, NekDouble> tmpx(npts), tmpy(npts);
249
250 // Determine 3D manifold orientation
251 m_xmap->BwdTrans(m_coeffs[m_manifold[0]], ptsx);
252 m_xmap->BwdTrans(m_coeffs[m_manifold[1]], ptsy);
253
254 Array<OneD, NekDouble> eta(2, 0.);
255 m_xmap->LocCoordToLocCollapsed(Lcoords, eta);
256 ClampLocCoords(eta, 0.);
257
258 m_xmap->LocCollapsedToLocCoord(eta, Lcoords);
259
260 // Perform newton iteration to find local coordinates
261 NewtonIterationForLocCoord(tmpcoords, ptsx, ptsy, Lcoords, dist);
262 }
263 if (m_coordim == 3)
264 {
265 Array<OneD, NekDouble> eta(2, 0.), xi(2, 0.);
266 m_xmap->LocCoordToLocCollapsed(Lcoords, eta);
267 ClampLocCoords(eta, 0.);
268 m_xmap->LocCollapsedToLocCoord(eta, xi);
269 int npts = m_xmap->GetTotPoints();
270 Array<OneD, NekDouble> ptsz(npts);
271 m_xmap->BwdTrans(m_coeffs[m_manifold[2]], ptsz);
272 NekDouble z = m_xmap->PhysEvaluate(xi, ptsz) - coords[m_manifold[2]];
273 if (Gtype == eDeformed)
274 {
275 dist = sqrt(z * z + dist * dist);
276 }
277 else
278 {
279 dist = fabs(z);
280 }
281 }
282 return dist;
283}
void NewtonIterationForLocCoord(const Array< OneD, const NekDouble > &coords, const Array< OneD, const NekDouble > &ptsx, const Array< OneD, const NekDouble > &ptsy, Array< OneD, NekDouble > &Lcoords, NekDouble &dist)
void SolveStraightEdgeQuad(const Array< OneD, const NekDouble > &coords, Array< OneD, NekDouble > &Lcoords)
virtual void v_FillGeom()
Populate the coordinate mapping Geometry::m_coeffs information from any children geometry elements.
Definition Geometry.cpp:357

References Nektar::SpatialDomains::Geometry::CalcGeomType(), Nektar::SpatialDomains::Geometry::ClampLocCoords(), Nektar::SpatialDomains::eDeformed, Nektar::SpatialDomains::eRegular, Nektar::SpatialDomains::Geometry::m_coeffs, Nektar::SpatialDomains::Geometry::m_coordim, Nektar::SpatialDomains::Geometry::m_invIsoParam, Nektar::SpatialDomains::Geometry::m_isoParameter, m_manifold, Nektar::SpatialDomains::Geometry::m_straightEdge, Nektar::SpatialDomains::Geometry::m_xmap, NewtonIterationForLocCoord(), SolveStraightEdgeQuad(), tinysimd::sqrt(), and Nektar::SpatialDomains::Geometry::v_FillGeom().

◆ v_GetShapeDim()

int Nektar::SpatialDomains::Geometry2D::v_GetShapeDim ( ) const
overrideprotectedvirtual

Get the object's shape dimension.

For example, a segment is one dimensional and quadrilateral is two dimensional.

Reimplemented from Nektar::SpatialDomains::Geometry.

Definition at line 285 of file Geometry2D.cpp.

286{
287 return 2;
288}

Member Data Documentation

◆ kDim

const int Nektar::SpatialDomains::Geometry2D::kDim = 2
static

Definition at line 56 of file Geometry2D.h.

◆ m_curve

Curve* Nektar::SpatialDomains::Geometry2D::m_curve
protected

◆ m_edgeNormal

Array<OneD, Array<OneD, NekDouble> > Nektar::SpatialDomains::Geometry2D::m_edgeNormal
protected

◆ m_manifold

Array<OneD, int> Nektar::SpatialDomains::Geometry2D::m_manifold
protected