Nektar++
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, CurveSharedPtr curve)
 
virtual ~Geometry2D ()
 
CurveSharedPtr GetCurve ()
 
- Public Member Functions inherited from Nektar::SpatialDomains::Geometry
 Geometry ()
 Default constructor. More...
 
 Geometry (int coordim)
 Constructor when supplied a coordinate dimension. More...
 
virtual ~Geometry ()
 Default destructor. More...
 
int GetCoordim () const
 Return the coordinate dimension of this object (i.e. the dimension of the space in which this object is embedded). More...
 
void SetCoordim (int coordim)
 Sets the coordinate dimension of this object (i.e. the dimension of the space in which this object is embedded). More...
 
GeomFactorsSharedPtr GetGeomFactors ()
 Get the geometric factors for this object, generating them if required. More...
 
GeomFactorsSharedPtr GetRefGeomFactors (const Array< OneD, const LibUtilities::BasisSharedPtr > &tbasis)
 
GeomFactorsSharedPtr GetMetricInfo ()
 Get the geometric factors for this object. More...
 
LibUtilities::ShapeType GetShapeType (void)
 Get the geometric shape type of this object. More...
 
int GetGlobalID (void) const
 Get the ID of this object. More...
 
void SetGlobalID (int globalid)
 Set the ID of this object. More...
 
int GetVid (int i) const
 Get the ID of vertex i of this object. More...
 
int GetEid (int i) const
 Get the ID of edge i of this object. More...
 
int GetFid (int i) const
 Get the ID of face i of this object. More...
 
int GetTid (int i) const
 Get the ID of trace i of this object. More...
 
PointGeomSharedPtr GetVertex (int i) const
 Returns vertex i of this object. More...
 
Geometry1DSharedPtr GetEdge (int i) const
 Returns edge i of this object. More...
 
Geometry2DSharedPtr GetFace (int i) const
 Returns face i of this object. More...
 
StdRegions::Orientation GetEorient (const int i) const
 Returns the orientation of edge i with respect to the ordering of edges in the standard element. More...
 
StdRegions::Orientation GetForient (const int i) const
 Returns the orientation of face i with respect to the ordering of faces in the standard element. More...
 
int GetNumVerts () const
 Get the number of vertices of this object. More...
 
int GetNumEdges () const
 Get the number of edges of this object. More...
 
int GetNumFaces () const
 Get the number of faces of this object. More...
 
int GetShapeDim () const
 Get the object's shape dimension. More...
 
StdRegions::StdExpansionSharedPtr GetXmap () const
 Return the mapping object Geometry::m_xmap that represents the coordinate transformation from standard element to physical element. More...
 
const Array< OneD, const NekDouble > & GetCoeffs (const int i) const
 Return the coefficients of the transformation Geometry::m_xmap in coordinate direction i. More...
 
void FillGeom ()
 Populate the coordinate mapping Geometry::m_coeffs information from any children geometry elements. More...
 
std::array< NekDouble, 6 > GetBoundingBox ()
 Generates the bounding box for the element. More...
 
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)\). More...
 
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)\). More...
 
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)\). More...
 
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. More...
 
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. More...
 
bool MinMaxCheck (const Array< OneD, const NekDouble > &gloCoord)
 Check if given global coord is within the BoundingBox of the element. More...
 
bool ClampLocCoords (Array< OneD, NekDouble > &locCoord, NekDouble tol=std::numeric_limits< NekDouble >::epsilon())
 Clamp local coords to be within standard regions [-1, 1]^dim. More...
 
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. More...
 
int GetVertexFaceMap (int i, int j) const
 Returns the standard element face IDs that are connected to a given vertex. More...
 
int GetEdgeFaceMap (int i, int j) const
 Returns the standard element edge IDs that are connected to a given face. More...
 
int GetEdgeNormalToFaceVert (int i, int j) const
 Returns the standard lement edge IDs that are normal to a given face vertex. More...
 
int GetDir (const int i, const int j=0) const
 Returns the element coordinate direction corresponding to a given face coordinate direction. More...
 
void Reset (CurveMap &curvedEdges, CurveMap &curvedFaces)
 Reset this geometry object: unset the current state, zero Geometry::m_coeffs and remove allocated GeomFactors. More...
 
void Setup ()
 

Static Public Attributes

static const int kDim = 2
 

Protected Member Functions

virtual 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. More...
 
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)
 
virtual int v_GetShapeDim () const override
 Get the object's shape dimension. More...
 
virtual PointGeomSharedPtr v_GetVertex (int i) const override
 
virtual Geometry1DSharedPtr v_GetEdge (int i) const override
 Returns edge i of this object. More...
 
virtual int v_GetNumVerts () const override
 Get the number of vertices of this object. More...
 
virtual int v_GetNumEdges () const override
 Get the number of edges of this object. More...
 
virtual StdRegions::Orientation v_GetEorient (const int i) const override
 Returns the orientation of edge i with respect to the ordering of edges in the standard element. More...
 
virtual NekDouble v_FindDistance (const Array< OneD, const NekDouble > &xs, Array< OneD, NekDouble > &xi) override
 
- Protected Member Functions inherited from Nektar::SpatialDomains::Geometry
void GenGeomFactors ()
 Handles generation of geometry factors. More...
 
virtual Geometry2DSharedPtr v_GetFace (int i) const
 Returns face i of this object. More...
 
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. More...
 
virtual int v_GetNumFaces () const
 Get the number of faces of this object. More...
 
virtual StdRegions::StdExpansionSharedPtr v_GetXmap () const
 Return the mapping object Geometry::m_xmap that represents the coordinate transformation from standard element to physical element. More...
 
virtual void v_FillGeom ()
 Populate the coordinate mapping Geometry::m_coeffs information from any children geometry elements. More...
 
virtual bool v_ContainsPoint (const Array< OneD, const NekDouble > &gloCoord, Array< OneD, NekDouble > &locCoord, NekDouble tol, NekDouble &dist)
 
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. More...
 
virtual int v_GetVertexEdgeMap (int i, int j) const
 Returns the standard element edge IDs that are connected to a given vertex. More...
 
virtual int v_GetVertexFaceMap (int i, int j) const
 Returns the standard element face IDs that are connected to a given vertex. More...
 
virtual int v_GetEdgeFaceMap (int i, int j) const
 Returns the standard element edge IDs that are connected to a given face. More...
 
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. More...
 
virtual int v_GetDir (const int faceidx, const int facedir) const
 Returns the element coordinate direction corresponding to a given face coordinate direction. More...
 
virtual void v_Reset (CurveMap &curvedEdges, CurveMap &curvedFaces)
 Reset this geometry object: unset the current state, zero Geometry::m_coeffs and remove allocated GeomFactors. More...
 
virtual void v_Setup ()
 
virtual void v_GenGeomFactors ()=0
 
void SetUpCoeffs (const int nCoeffs)
 Initialise the Geometry::m_coeffs array. More...
 

Protected Attributes

PointGeomVector m_verts
 
SegGeomVector m_edges
 
std::vector< StdRegions::Orientationm_eorient
 
CurveSharedPtr m_curve
 
- Protected Attributes inherited from Nektar::SpatialDomains::Geometry
int m_coordim
 Coordinate dimension of this geometry object. More...
 
GeomFactorsSharedPtr m_geomFactors
 Geometric factors. More...
 
GeomState m_geomFactorsState
 State of the geometric factors. More...
 
StdRegions::StdExpansionSharedPtr m_xmap
 \(\chi\) mapping containing isoparametric transformation. More...
 
GeomState m_state
 Enumeration to dictate whether coefficients are filled. More...
 
bool m_setupState
 Wether or not the setup routines have been run. More...
 
GeomType m_geomType
 Type of geometry. More...
 
LibUtilities::ShapeType m_shapeType
 Type of shape. More...
 
int m_globalID
 Global ID. More...
 
Array< OneD, Array< OneD, NekDouble > > m_coeffs
 Array containing expansion coefficients of m_xmap. More...
 
Array< OneD, NekDoublem_boundingBox
 Array containing bounding box. More...
 

Additional Inherited Members

- Static Protected Member Functions inherited from Nektar::SpatialDomains::Geometry
static GeomFactorsSharedPtr ValidateRegGeomFactor (GeomFactorsSharedPtr geomFactor)
 Check to see if a geometric factor has already been created that contains the same regular information. More...
 
- Static Protected Attributes inherited from Nektar::SpatialDomains::Geometry
static GeomFactorsVector m_regGeomFactorsManager
 

Detailed Description

2D geometry information

Definition at line 68 of file Geometry2D.h.

Constructor & Destructor Documentation

◆ Geometry2D() [1/2]

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

Definition at line 50 of file Geometry2D.cpp.

51 {
52 }

◆ Geometry2D() [2/2]

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

Definition at line 54 of file Geometry2D.cpp.

55  : Geometry(coordim), m_curve(curve)
56 {
57  ASSERTL0(m_coordim > 1,
58  "Coordinate dimension should be at least 2 for a 2D geometry");
59 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
Geometry()
Default constructor.
Definition: Geometry.cpp:54
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 ( )
virtual

Definition at line 61 of file Geometry2D.cpp.

62 {
63 }

Member Function Documentation

◆ GetCurve()

CurveSharedPtr Nektar::SpatialDomains::Geometry2D::GetCurve ( )
inline

Definition at line 76 of file Geometry2D.h.

77  {
78  return m_curve;
79  }

References m_curve.

◆ 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 65 of file Geometry2D.cpp.

70 {
71  // Maximum iterations for convergence
72  const int MaxIterations = NekConstants::kNewtonIterations;
73  // |x-xp|^2 < EPSILON error tolerance
74  const NekDouble Tol = 1.e-8;
75  // |r,s| > LcoordDIV stop the search
76  const NekDouble LcoordDiv = 15.0;
77 
78  Array<OneD, const NekDouble> Jac =
79  m_geomFactors->GetJac(m_xmap->GetPointsKeys());
80 
81  NekDouble ScaledTol =
82  Vmath::Vsum(Jac.size(), Jac, 1) / ((NekDouble)Jac.size());
83  ScaledTol *= Tol;
84 
85  NekDouble xmap, ymap, F1, F2;
86  NekDouble derx_1, derx_2, dery_1, dery_2, jac;
87 
88  // save intiial guess for later reference if required.
89  NekDouble init0 = Lcoords[0], init1 = Lcoords[1];
90 
91  Array<OneD, NekDouble> DxD1(ptsx.size());
92  Array<OneD, NekDouble> DxD2(ptsx.size());
93  Array<OneD, NekDouble> DyD1(ptsx.size());
94  Array<OneD, NekDouble> DyD2(ptsx.size());
95 
96  // Ideally this will be stored in m_geomfactors
97  m_xmap->PhysDeriv(ptsx, DxD1, DxD2);
98  m_xmap->PhysDeriv(ptsy, DyD1, DyD2);
99 
100  int cnt = 0;
101  Array<OneD, DNekMatSharedPtr> I(2);
102  Array<OneD, NekDouble> eta(2);
103 
104  F1 = F2 = 2000; // Starting value of Function
105  NekDouble resid = sqrt(F1 * F1 + F2 * F2);
106  while (cnt++ < MaxIterations)
107  {
108  // evaluate lagrange interpolant at Lcoords
109  m_xmap->LocCoordToLocCollapsed(Lcoords, eta);
110  I[0] = m_xmap->GetBasis(0)->GetI(eta);
111  I[1] = m_xmap->GetBasis(1)->GetI(eta + 1);
112 
113  // calculate the global point `corresponding to Lcoords
114  xmap = m_xmap->PhysEvaluate(I, ptsx);
115  ymap = m_xmap->PhysEvaluate(I, ptsy);
116 
117  F1 = coords[0] - xmap;
118  F2 = coords[1] - ymap;
119 
120  if (F1 * F1 + F2 * F2 < ScaledTol)
121  {
122  resid = sqrt(F1 * F1 + F2 * F2);
123  break;
124  }
125 
126  // Interpolate derivative metric at Lcoords
127  derx_1 = m_xmap->PhysEvaluate(I, DxD1);
128  derx_2 = m_xmap->PhysEvaluate(I, DxD2);
129  dery_1 = m_xmap->PhysEvaluate(I, DyD1);
130  dery_2 = m_xmap->PhysEvaluate(I, DyD2);
131 
132  jac = dery_2 * derx_1 - dery_1 * derx_2;
133 
134  // use analytical inverse of derivitives which are
135  // also similar to those of metric factors.
136  Lcoords[0] =
137  Lcoords[0] +
138  (dery_2 * (coords[0] - xmap) - derx_2 * (coords[1] - ymap)) / jac;
139 
140  Lcoords[1] =
141  Lcoords[1] +
142  (-dery_1 * (coords[0] - xmap) + derx_1 * (coords[1] - ymap)) / jac;
143 
144  if (!(std::isfinite(Lcoords[0]) && std::isfinite(Lcoords[1])))
145  {
146  dist = 1e16;
147  std::ostringstream ss;
148  ss << "nan or inf found in NewtonIterationForLocCoord in element "
149  << GetGlobalID();
150  WARNINGL1(false, ss.str());
151  return;
152  }
153  if (fabs(Lcoords[0]) > LcoordDiv || fabs(Lcoords[1]) > LcoordDiv)
154  {
155  break; // lcoords have diverged so stop iteration
156  }
157  }
158 
159  m_xmap->LocCoordToLocCollapsed(Lcoords, eta);
160  if (ClampLocCoords(eta, 0.))
161  {
162  I[0] = m_xmap->GetBasis(0)->GetI(eta);
163  I[1] = m_xmap->GetBasis(1)->GetI(eta + 1);
164  // calculate the global point corresponding to Lcoords
165  xmap = m_xmap->PhysEvaluate(I, ptsx);
166  ymap = m_xmap->PhysEvaluate(I, ptsy);
167  F1 = coords[0] - xmap;
168  F2 = coords[1] - ymap;
169  dist = sqrt(F1 * F1 + F2 * F2);
170  }
171  else
172  {
173  dist = 0.;
174  }
175 
176  if (cnt >= MaxIterations)
177  {
178  Array<OneD, NekDouble> collCoords(2);
179  m_xmap->LocCoordToLocCollapsed(Lcoords, collCoords);
180 
181  // if coordinate is inside element dump error!
182  if ((collCoords[0] >= -1.0 && collCoords[0] <= 1.0) &&
183  (collCoords[1] >= -1.0 && collCoords[1] <= 1.0))
184  {
185  std::ostringstream ss;
186 
187  ss << "Reached MaxIterations (" << MaxIterations
188  << ") in Newton iteration ";
189  ss << "Init value (" << setprecision(4) << init0 << "," << init1
190  << ","
191  << ") ";
192  ss << "Fin value (" << Lcoords[0] << "," << Lcoords[1] << ","
193  << ") ";
194  ss << "Resid = " << resid << " Tolerance = " << sqrt(ScaledTol);
195 
196  WARNINGL1(cnt < MaxIterations, ss.str());
197  }
198  }
199 }
#define WARNINGL1(condition, msg)
Definition: ErrorUtil.hpp:250
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:510
int GetGlobalID(void) const
Get the ID of this object.
Definition: Geometry.h:320
StdRegions::StdExpansionSharedPtr m_xmap
mapping containing isoparametric transformation.
Definition: Geometry.h:190
GeomFactorsSharedPtr m_geomFactors
Geometric factors.
Definition: Geometry.h:186
static const unsigned int kNewtonIterations
double NekDouble
T Vsum(int n, const T *x, const int incx)
Subtract return sum(x)
Definition: Vmath.cpp:895
scalarT< T > sqrt(scalarT< T > in)
Definition: scalar.hpp:294

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

Referenced by v_GetLocCoords().

◆ 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 354 of file Geometry2D.cpp.

356 {
357  if (m_geomFactors->GetGtype() == eRegular)
358  {
359  xiOut = Array<OneD, NekDouble>(2, 0.0);
360 
361  GetLocCoords(xs, xiOut);
362  ClampLocCoords(xiOut);
363 
364  Array<OneD, NekDouble> gloCoord(3);
365  gloCoord[0] = GetCoord(0, xiOut);
366  gloCoord[1] = GetCoord(1, xiOut);
367  gloCoord[2] = GetCoord(2, xiOut);
368 
369  return sqrt((xs[0] - gloCoord[0]) * (xs[0] - gloCoord[0]) +
370  (xs[1] - gloCoord[1]) * (xs[1] - gloCoord[1]) +
371  (xs[2] - gloCoord[2]) * (xs[2] - gloCoord[2]));
372  }
373  // If deformed edge then the inverse mapping is non-linear so need to
374  // numerically solve for the local coordinate
375  else if (m_geomFactors->GetGtype() == eDeformed)
376  {
377  // Choose starting based on closest quad
378  Array<OneD, NekDouble> xi(2, 0.0), eta(2, 0.0);
379  m_xmap->LocCollapsedToLocCoord(eta, xi);
380 
381  // Armijo constants:
382  // https://en.wikipedia.org/wiki/Backtracking_line_search
383  const NekDouble c1 = 1e-4, c2 = 0.9;
384 
385  int nq = m_xmap->GetTotPoints();
386 
387  Array<OneD, NekDouble> x(nq), y(nq), z(nq);
388  m_xmap->BwdTrans(m_coeffs[0], x);
389  m_xmap->BwdTrans(m_coeffs[1], y);
390  m_xmap->BwdTrans(m_coeffs[2], z);
391 
392  Array<OneD, NekDouble> xderxi1(nq, 0.0), yderxi1(nq, 0.0),
393  zderxi1(nq, 0.0), xderxi2(nq, 0.0), yderxi2(nq, 0.0),
394  zderxi2(nq, 0.0), xderxi1xi1(nq, 0.0), yderxi1xi1(nq, 0.0),
395  zderxi1xi1(nq, 0.0), xderxi1xi2(nq, 0.0), yderxi1xi2(nq, 0.0),
396  zderxi1xi2(nq, 0.0), xderxi2xi1(nq, 0.0), yderxi2xi1(nq, 0.0),
397  zderxi2xi1(nq, 0.0), xderxi2xi2(nq, 0.0), yderxi2xi2(nq, 0.0),
398  zderxi2xi2(nq, 0.0);
399 
400  // Get first & second derivatives & partial derivatives of x,y,z values
401  std::array<NekDouble, 3> xc_derxi, yc_derxi, zc_derxi;
402 
403  m_xmap->PhysDeriv(x, xderxi1, xderxi2);
404  m_xmap->PhysDeriv(y, yderxi1, yderxi2);
405  m_xmap->PhysDeriv(z, zderxi1, zderxi2);
406 
407  m_xmap->PhysDeriv(xderxi1, xderxi1xi1, xderxi1xi2);
408  m_xmap->PhysDeriv(yderxi1, yderxi1xi1, yderxi1xi2);
409  m_xmap->PhysDeriv(zderxi1, zderxi1xi1, zderxi1xi2);
410 
411  m_xmap->PhysDeriv(yderxi2, yderxi2xi1, yderxi2xi2);
412  m_xmap->PhysDeriv(xderxi2, xderxi2xi1, xderxi2xi2);
413  m_xmap->PhysDeriv(zderxi2, zderxi2xi1, zderxi2xi2);
414 
415  // Minimisation loop (Quasi-newton method)
416  NekDouble fx_prev = std::numeric_limits<NekDouble>::max();
417  for (int i = 0; i < NekConstants::kNewtonIterations; ++i)
418  {
419  // Compute the objective function, f(x_k) and its derivatives
420  NekDouble xc = m_xmap->PhysEvaluate(xi, x, xc_derxi);
421  NekDouble yc = m_xmap->PhysEvaluate(xi, y, yc_derxi);
422  NekDouble zc = m_xmap->PhysEvaluate(xi, z, zc_derxi);
423 
424  NekDouble xc_derxi1xi1 = m_xmap->PhysEvaluate(xi, xderxi1xi1);
425  NekDouble yc_derxi1xi1 = m_xmap->PhysEvaluate(xi, yderxi1xi1);
426  NekDouble zc_derxi1xi1 = m_xmap->PhysEvaluate(xi, zderxi1xi1);
427 
428  NekDouble xc_derxi1xi2 = m_xmap->PhysEvaluate(xi, xderxi1xi2);
429  NekDouble yc_derxi1xi2 = m_xmap->PhysEvaluate(xi, yderxi1xi2);
430  NekDouble zc_derxi1xi2 = m_xmap->PhysEvaluate(xi, zderxi1xi2);
431 
432  NekDouble xc_derxi2xi2 = m_xmap->PhysEvaluate(xi, xderxi2xi2);
433  NekDouble yc_derxi2xi2 = m_xmap->PhysEvaluate(xi, yderxi2xi2);
434  NekDouble zc_derxi2xi2 = m_xmap->PhysEvaluate(xi, zderxi2xi2);
435 
436  // Objective function is the distance to the search point
437  NekDouble xdiff = xc - xs[0];
438  NekDouble ydiff = yc - xs[1];
439  NekDouble zdiff = zc - xs[2];
440 
441  NekDouble fx = xdiff * xdiff + ydiff * ydiff + zdiff * zdiff;
442 
443  NekDouble fx_derxi1 = 2.0 * xdiff * xc_derxi[0] +
444  2.0 * ydiff * yc_derxi[0] +
445  2.0 * zdiff * zc_derxi[0];
446 
447  NekDouble fx_derxi2 = 2.0 * xdiff * xc_derxi[1] +
448  2.0 * ydiff * yc_derxi[1] +
449  2.0 * zdiff * zc_derxi[1];
450 
451  NekDouble fx_derxi1xi1 =
452  2.0 * xdiff * xc_derxi1xi1 + 2.0 * xc_derxi[0] * xc_derxi[0] +
453  2.0 * ydiff * yc_derxi1xi1 + 2.0 * yc_derxi[0] * yc_derxi[0] +
454  2.0 * zdiff * zc_derxi1xi1 + 2.0 * zc_derxi[0] * zc_derxi[0];
455 
456  NekDouble fx_derxi1xi2 =
457  2.0 * xdiff * xc_derxi1xi2 + 2.0 * xc_derxi[1] * xc_derxi[0] +
458  2.0 * ydiff * yc_derxi1xi2 + 2.0 * yc_derxi[1] * yc_derxi[0] +
459  2.0 * zdiff * zc_derxi1xi2 + 2.0 * zc_derxi[1] * zc_derxi[0];
460 
461  NekDouble fx_derxi2xi2 =
462  2.0 * xdiff * xc_derxi2xi2 + 2.0 * xc_derxi[1] * xc_derxi[1] +
463  2.0 * ydiff * yc_derxi2xi2 + 2.0 * yc_derxi[1] * yc_derxi[1] +
464  2.0 * zdiff * zc_derxi2xi2 + 2.0 * zc_derxi[1] * zc_derxi[1];
465 
466  // Jacobian
467  NekDouble jac[2];
468  jac[0] = fx_derxi1;
469  jac[1] = fx_derxi2;
470 
471  // Inverse of 2x2 hessian
472  NekDouble hessInv[2][2];
473 
474  NekDouble det =
475  1 / (fx_derxi1xi1 * fx_derxi2xi2 - fx_derxi1xi2 * fx_derxi1xi2);
476  hessInv[0][0] = det * fx_derxi2xi2;
477  hessInv[0][1] = det * -fx_derxi1xi2;
478  hessInv[1][0] = det * -fx_derxi1xi2;
479  hessInv[1][1] = det * fx_derxi1xi1;
480 
481  // Check for convergence
482  if (abs(fx - fx_prev) < 1e-12)
483  {
484  fx_prev = fx;
485  break;
486  }
487  else
488  {
489  fx_prev = fx;
490  }
491 
492  NekDouble gamma = 1.0;
493  bool conv = false;
494 
495  // Search direction: Newton's method
496  NekDouble pk[2];
497  pk[0] = -(hessInv[0][0] * jac[0] + hessInv[1][0] * jac[1]);
498  pk[1] = -(hessInv[0][1] * jac[0] + hessInv[1][1] * jac[1]);
499 
500  // Backtracking line search
501  while (gamma > 1e-10)
502  {
503  Array<OneD, NekDouble> xi_pk(2);
504  xi_pk[0] = xi[0] + pk[0] * gamma;
505  xi_pk[1] = xi[1] + pk[1] * gamma;
506 
507  Array<OneD, NekDouble> eta_pk(2, 0.0);
508  m_xmap->LocCoordToLocCollapsed(xi_pk, eta_pk);
509 
510  if (eta_pk[0] <
511  (-1 - std::numeric_limits<NekDouble>::epsilon()) ||
512  eta_pk[0] >
513  (1 + std::numeric_limits<NekDouble>::epsilon()) ||
514  eta_pk[1] <
515  (-1 - std::numeric_limits<NekDouble>::epsilon()) ||
516  eta_pk[1] > (1 + std::numeric_limits<NekDouble>::epsilon()))
517  {
518  gamma /= 2.0;
519  continue;
520  }
521 
522  std::array<NekDouble, 3> xc_pk_derxi, yc_pk_derxi, zc_pk_derxi;
523 
524  NekDouble xc_pk = m_xmap->PhysEvaluate(xi_pk, x, xc_pk_derxi);
525  NekDouble yc_pk = m_xmap->PhysEvaluate(xi_pk, y, yc_pk_derxi);
526  NekDouble zc_pk = m_xmap->PhysEvaluate(xi_pk, z, zc_pk_derxi);
527 
528  NekDouble xc_pk_diff = xc_pk - xs[0];
529  NekDouble yc_pk_diff = yc_pk - xs[1];
530  NekDouble zc_pk_diff = zc_pk - xs[2];
531 
532  NekDouble fx_pk = xc_pk_diff * xc_pk_diff +
533  yc_pk_diff * yc_pk_diff +
534  zc_pk_diff * zc_pk_diff;
535 
536  NekDouble fx_pk_derxi1 = 2.0 * xc_pk_diff * xc_pk_derxi[0] +
537  2.0 * yc_pk_diff * yc_pk_derxi[0] +
538  2.0 * zc_pk_diff * zc_pk_derxi[0];
539 
540  NekDouble fx_pk_derxi2 = 2.0 * xc_pk_diff * xc_pk_derxi[1] +
541  2.0 * yc_pk_diff * yc_pk_derxi[1] +
542  2.0 * zc_pk_diff * zc_pk_derxi[1];
543 
544  // Check Wolfe conditions using Armijo constants
545  // https://en.wikipedia.org/wiki/Wolfe_conditions
546  NekDouble tmp = pk[0] * fx_derxi1 + pk[1] * fx_derxi2;
547  NekDouble tmp2 = pk[0] * fx_pk_derxi1 + pk[1] * fx_pk_derxi2;
548  if ((fx_pk - (fx + c1 * gamma * tmp)) <
549  std::numeric_limits<NekDouble>::epsilon() &&
550  (-tmp2 - (-c2 * tmp)) <
551  std::numeric_limits<NekDouble>::epsilon())
552  {
553  conv = true;
554  break;
555  }
556 
557  gamma /= 2.0;
558  }
559 
560  if (!conv)
561  {
562  break;
563  }
564 
565  xi[0] += gamma * pk[0];
566  xi[1] += gamma * pk[1];
567  }
568 
569  xiOut = xi;
570  return sqrt(fx_prev);
571  }
572  else
573  {
574  ASSERTL0(false, "Geometry type unknown")
575  }
576 
577  return -1.0;
578 }
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:548
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:538
Array< OneD, Array< OneD, NekDouble > > m_coeffs
Array containing expansion coefficients of m_xmap.
Definition: Geometry.h:202
@ eRegular
Geometry is straight-sided with constant geometric factors.
@ eDeformed
Geometry is curved or has non-constant factors.
scalarT< T > abs(scalarT< T > in)
Definition: scalar.hpp:298

References tinysimd::abs(), ASSERTL0, Nektar::SpatialDomains::Geometry::ClampLocCoords(), Nektar::SpatialDomains::eDeformed, Nektar::SpatialDomains::eRegular, Nektar::SpatialDomains::Geometry::GetCoord(), Nektar::SpatialDomains::Geometry::GetLocCoords(), Nektar::NekConstants::kNewtonIterations, Nektar::SpatialDomains::Geometry::m_coeffs, Nektar::SpatialDomains::Geometry::m_geomFactors, Nektar::SpatialDomains::Geometry::m_xmap, and tinysimd::sqrt().

◆ v_GetEdge()

Geometry1DSharedPtr Nektar::SpatialDomains::Geometry2D::v_GetEdge ( int  i) const
overrideprotectedvirtual

Returns edge i of this object.

Reimplemented from Nektar::SpatialDomains::Geometry.

Definition at line 337 of file Geometry2D.cpp.

338 {
339  ASSERTL2(i >= 0 && i < m_edges.size(), "Index out of range");
340  return m_edges[i];
341 }
#define ASSERTL2(condition, msg)
Assert Level 2 – Debugging which is used FULLDEBUG compilation mode. This level assert is designed to...
Definition: ErrorUtil.hpp:272

References ASSERTL2, and m_edges.

◆ v_GetEorient()

StdRegions::Orientation Nektar::SpatialDomains::Geometry2D::v_GetEorient ( const int  i) const
overrideprotectedvirtual

Returns the orientation of edge i with respect to the ordering of edges in the standard element.

Reimplemented from Nektar::SpatialDomains::Geometry.

Definition at line 343 of file Geometry2D.cpp.

344 {
345  ASSERTL2(i >= 0 && i < m_eorient.size(), "Index out of range");
346  return m_eorient[i];
347 }
std::vector< StdRegions::Orientation > m_eorient
Definition: Geometry2D.h:84

References ASSERTL2, and m_eorient.

◆ 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 201 of file Geometry2D.cpp.

203 {
204  NekDouble dist = 0.;
205  if (GetMetricInfo()->GetGtype() == eRegular)
206  {
207  int v2;
209  {
210  v2 = 2;
211  }
213  {
214  v2 = 3;
215  }
216  else
217  {
218  v2 = 2;
219  ASSERTL0(false, "unrecognized 2D element type");
220  }
221 
222  NekDouble coords2 = (m_coordim == 3) ? coords[2] : 0.0;
223  PointGeom r(m_coordim, 0, coords[0], coords[1], coords2);
224 
225  // Edges
226  PointGeom er0, e10, e20;
227  PointGeom norm, orth1, orth2;
228  er0.Sub(r, *m_verts[0]);
229  e10.Sub(*m_verts[1], *m_verts[0]);
230  e20.Sub(*m_verts[v2], *m_verts[0]);
231 
232  // Obtain normal to element plane
233  norm.Mult(e10, e20);
234  // Obtain vector which are proportional to normal of e10 and e20.
235  orth1.Mult(norm, e10);
236  orth2.Mult(norm, e20);
237 
238  // Calculate length using L/|dv1| = (x-v0).n1/(dv1.n1) for coordiante 1
239  // Then rescale to [-1,1].
240  Lcoords[0] = er0.dot(orth2) / e10.dot(orth2);
241  Lcoords[0] = 2. * Lcoords[0] - 1.;
242  Lcoords[1] = er0.dot(orth1) / e20.dot(orth1);
243  Lcoords[1] = 2. * Lcoords[1] - 1.;
244 
245  // Set distance
246  Array<OneD, NekDouble> eta(2, 0.);
247  m_xmap->LocCoordToLocCollapsed(Lcoords, eta);
248  if (ClampLocCoords(eta, 0.))
249  {
250  Array<OneD, NekDouble> xi(2, 0.);
251  m_xmap->LocCollapsedToLocCoord(eta, xi);
252  xi[0] = (xi[0] + 1.) * 0.5; // re-scaled to ratio [0, 1]
253  xi[1] = (xi[1] + 1.) * 0.5;
254  for (int i = 0; i < m_coordim; ++i)
255  {
256  NekDouble tmp = xi[0] * e10[i] + xi[1] * e20[i] - er0[i];
257  dist += tmp * tmp;
258  }
259  dist = sqrt(dist);
260  }
261  }
262  else
263  {
264  v_FillGeom();
265  // Determine nearest point of coords to values in m_xmap
266  int npts = m_xmap->GetTotPoints();
267  Array<OneD, NekDouble> ptsx(npts), ptsy(npts);
268  Array<OneD, NekDouble> tmpx(npts), tmpy(npts);
269 
270  // Determine 3D manifold orientation
271  int idx = 0, idy = 1;
272  if (m_coordim == 3)
273  {
274  PointGeom e01, e21, norm;
275  e01.Sub(*m_verts[0], *m_verts[1]);
276  e21.Sub(*m_verts[2], *m_verts[1]);
277  norm.Mult(e01, e21);
278  int tmpi = 0;
279  double tmp = std::fabs(norm[0]);
280  if (tmp < fabs(norm[1]))
281  {
282  tmp = fabs(norm[1]);
283  tmpi = 1;
284  }
285  if (tmp < fabs(norm[2]))
286  {
287  tmpi = 2;
288  }
289  idx = (tmpi + 1) % 3;
290  idy = (tmpi + 2) % 3;
291  }
292  Array<OneD, NekDouble> tmpcoords(2);
293  tmpcoords[0] = coords[idx];
294  tmpcoords[1] = coords[idy];
295 
296  m_xmap->BwdTrans(m_coeffs[idx], ptsx);
297  m_xmap->BwdTrans(m_coeffs[idy], ptsy);
298 
299  const Array<OneD, const NekDouble> za = m_xmap->GetPoints(0);
300  const Array<OneD, const NekDouble> zb = m_xmap->GetPoints(1);
301 
302  // guess the first local coords based on nearest point
303  Vmath::Sadd(npts, -tmpcoords[0], ptsx, 1, tmpx, 1);
304  Vmath::Sadd(npts, -tmpcoords[1], ptsy, 1, tmpy, 1);
305  Vmath::Vmul(npts, tmpx, 1, tmpx, 1, tmpx, 1);
306  Vmath::Vvtvp(npts, tmpy, 1, tmpy, 1, tmpx, 1, tmpx, 1);
307 
308  int min_i = Vmath::Imin(npts, tmpx, 1);
309 
310  Array<OneD, NekDouble> eta(2, 0.);
311  eta[0] = za[min_i % za.size()];
312  eta[1] = zb[min_i / za.size()];
313  m_xmap->LocCollapsedToLocCoord(eta, Lcoords);
314 
315  // Perform newton iteration to find local coordinates
316  NewtonIterationForLocCoord(tmpcoords, ptsx, ptsy, Lcoords, dist);
317  }
318  return dist;
319 }
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)
Definition: Geometry2D.cpp:65
virtual void v_FillGeom()
Populate the coordinate mapping Geometry::m_coeffs information from any children geometry elements.
Definition: Geometry.cpp:367
LibUtilities::ShapeType m_shapeType
Type of shape.
Definition: Geometry.h:198
GeomFactorsSharedPtr GetMetricInfo()
Get the geometric factors for this object.
Definition: Geometry.h:304
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:209
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:574
int Imin(int n, const T *x, const int incx)
Return the index of the minimum element in x.
Definition: Vmath.cpp:1023
void Sadd(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Add scalar y = alpha + x.
Definition: Vmath.cpp:384

References ASSERTL0, Nektar::SpatialDomains::Geometry::ClampLocCoords(), Nektar::SpatialDomains::PointGeom::dot(), Nektar::LibUtilities::eQuadrilateral, Nektar::SpatialDomains::eRegular, Nektar::LibUtilities::eTriangle, Nektar::SpatialDomains::Geometry::GetMetricInfo(), Vmath::Imin(), Nektar::SpatialDomains::Geometry::m_coeffs, Nektar::SpatialDomains::Geometry::m_coordim, Nektar::SpatialDomains::Geometry::m_shapeType, m_verts, Nektar::SpatialDomains::Geometry::m_xmap, Nektar::SpatialDomains::PointGeom::Mult(), NewtonIterationForLocCoord(), Vmath::Sadd(), tinysimd::sqrt(), Nektar::SpatialDomains::PointGeom::Sub(), Nektar::SpatialDomains::Geometry::v_FillGeom(), Vmath::Vmul(), and Vmath::Vvtvp().

◆ v_GetNumEdges()

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

Get the number of edges of this object.

Reimplemented from Nektar::SpatialDomains::Geometry.

Definition at line 326 of file Geometry2D.cpp.

327 {
328  return m_edges.size();
329 }

References m_edges.

◆ v_GetNumVerts()

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

Get the number of vertices of this object.

Reimplemented from Nektar::SpatialDomains::Geometry.

Definition at line 321 of file Geometry2D.cpp.

322 {
323  return m_verts.size();
324 }

References m_verts.

◆ 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 349 of file Geometry2D.cpp.

350 {
351  return 2;
352 }

◆ v_GetVertex()

PointGeomSharedPtr Nektar::SpatialDomains::Geometry2D::v_GetVertex ( int  i) const
overrideprotectedvirtual

Implements Nektar::SpatialDomains::Geometry.

Definition at line 331 of file Geometry2D.cpp.

332 {
333  ASSERTL2(i >= 0 && i < m_verts.size(), "Index out of range");
334  return m_verts[i];
335 }

References ASSERTL2, and m_verts.

Member Data Documentation

◆ kDim

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

Definition at line 75 of file Geometry2D.h.

◆ m_curve

CurveSharedPtr Nektar::SpatialDomains::Geometry2D::m_curve
protected

◆ m_edges

SegGeomVector Nektar::SpatialDomains::Geometry2D::m_edges
protected

◆ m_eorient

std::vector<StdRegions::Orientation> Nektar::SpatialDomains::Geometry2D::m_eorient
protected

◆ m_verts

PointGeomVector Nektar::SpatialDomains::Geometry2D::m_verts
protected