Nektar++
Public Member Functions | Protected Member Functions | Protected Attributes | Private Types | List of all members
Nektar::LibUtilities::NodalUtilTetrahedron Class Reference

Specialisation of the NodalUtil class to support nodal tetrahedral elements. More...

#include <NodalUtil.h>

Inheritance diagram for Nektar::LibUtilities::NodalUtilTetrahedron:
[legend]

Public Member Functions

 NodalUtilTetrahedron (int degree, Array< OneD, NekDouble > r, Array< OneD, NekDouble > s, Array< OneD, NekDouble > t)
 Construct the nodal utility class for a tetrahedron. More...
 
virtual ~NodalUtilTetrahedron ()
 
- Public Member Functions inherited from Nektar::LibUtilities::NodalUtil
virtual ~NodalUtil ()=default
 
NekVector< NekDoubleGetWeights ()
 Obtain the integration weights for the given nodal distribution. More...
 
SharedMatrix GetVandermonde ()
 Return the Vandermonde matrix for the nodal distribution. More...
 
SharedMatrix GetVandermondeForDeriv (int dir)
 Return the Vandermonde matrix of the derivative of the basis functions for the nodal distribution. More...
 
SharedMatrix GetDerivMatrix (int dir)
 Return the derivative matrix for the nodal distribution. More...
 
SharedMatrix GetInterpolationMatrix (Array< OneD, Array< OneD, NekDouble >> &xi)
 Construct the interpolation matrix used to evaluate the basis at the points xi inside the element. More...
 

Protected Member Functions

virtual NekVector< NekDoublev_OrthoBasis (const int mode) override
 Return the value of the modal functions for the tetrahedral element at the nodal points m_xi for a given mode. More...
 
virtual NekVector< NekDoublev_OrthoBasisDeriv (const int dir, const int mode) override
 Return the value of the derivative of the modal functions for the tetrahedral element at the nodal points m_xi for a given mode. More...
 
virtual std::shared_ptr< NodalUtilv_CreateUtil (Array< OneD, Array< OneD, NekDouble >> &xi) override
 Construct a NodalUtil object of the appropriate element type for a given set of points. More...
 
virtual NekDouble v_ModeZeroIntegral () override
 Return the value of the integral of the zero-th mode for this element. More...
 
virtual int v_NumModes () override
 Calculate the number of degrees of freedom for this element. More...
 
- Protected Member Functions inherited from Nektar::LibUtilities::NodalUtil
 NodalUtil (int degree, int dim)
 Set up the NodalUtil object. More...
 

Protected Attributes

std::vector< Modem_ordering
 Mapping from the \( (i,j,k) \) indexing of the basis to a continuous ordering. More...
 
Array< OneD, Array< OneD, NekDouble > > m_eta
 Collapsed coordinates \( (\eta_1, \eta_2, \eta_3) \) of the nodal points. More...
 
- Protected Attributes inherited from Nektar::LibUtilities::NodalUtil
int m_dim
 Dimension of the nodal element. More...
 
int m_degree
 Degree of the nodal element. More...
 
int m_numPoints
 Total number of nodal points. More...
 
Array< OneD, Array< OneD, NekDouble > > m_xi
 Coordinates of the nodal points defining the basis. More...
 

Private Types

typedef std::tuple< int, int, int > Mode
 

Detailed Description

Specialisation of the NodalUtil class to support nodal tetrahedral elements.

Definition at line 213 of file NodalUtil.h.

Member Typedef Documentation

◆ Mode

typedef std::tuple<int, int, int> Nektar::LibUtilities::NodalUtilTetrahedron::Mode
private

Definition at line 215 of file NodalUtil.h.

Constructor & Destructor Documentation

◆ NodalUtilTetrahedron()

Nektar::LibUtilities::NodalUtilTetrahedron::NodalUtilTetrahedron ( int  degree,
Array< OneD, NekDouble r,
Array< OneD, NekDouble s,
Array< OneD, NekDouble t 
)

Construct the nodal utility class for a tetrahedron.

The constructor of this class sets up two member variables used in the evaluation of the orthogonal basis:

  • NodalUtilTetrahedron::m_eta is used to construct the collapsed coordinate locations of the nodal points \( (\eta_1, \eta_2, \eta_3) \) inside the cube \([-1,1]^3\) on which the orthogonal basis functions are defined.
  • NodalUtilTetrahedron::m_ordering constructs a mapping from the index set \( I = \{ (i,j,k)\ |\ 0\leq i,j,k \leq P, i+j \leq P, i+j+k \leq P \}\) to an ordering \( 0 \leq m(ijk) \leq (P+1)(P+2)(P+3)/6 \) that defines the monomials \( \xi_1^i \xi_2^j \xi_3^k \) that span the tetrahedral space. This is then used to calculate which \( (i,j,k) \) triple (represented as a tuple) corresponding to a column of the Vandermonde matrix when calculating the orthogonal polynomials.
Parameters
degreePolynomial order of this nodal tetrahedron
r\( \xi_1 \)-coordinates of nodal points in the standard element.
s\( \xi_2 \)-coordinates of nodal points in the standard element.
t\( \xi_3 \)-coordinates of nodal points in the standard element.

Definition at line 414 of file NodalUtil.cpp.

417  : NodalUtil(degree, 3), m_eta(3)
418 {
419  m_numPoints = r.size();
420  m_xi[0] = r;
421  m_xi[1] = s;
422  m_xi[2] = t;
423 
424  for (int i = 0; i <= m_degree; ++i)
425  {
426  for (int j = 0; j <= m_degree - i; ++j)
427  {
428  for (int k = 0; k <= m_degree - i - j; ++k)
429  {
430  m_ordering.push_back(Mode(i, j, k));
431  }
432  }
433  }
434 
435  // Calculate collapsed coordinates from r/s values
436  m_eta[0] = Array<OneD, NekDouble>(m_numPoints);
437  m_eta[1] = Array<OneD, NekDouble>(m_numPoints);
438  m_eta[2] = Array<OneD, NekDouble>(m_numPoints);
439 
440  for (int i = 0; i < m_numPoints; ++i)
441  {
442  if (fabs(m_xi[2][i] - 1.0) < NekConstants::kNekZeroTol)
443  {
444  // Very top point of the tetrahedron
445  m_eta[0][i] = -1.0;
446  m_eta[1][i] = -1.0;
447  m_eta[2][i] = m_xi[2][i];
448  }
449  else
450  {
451  if (fabs(m_xi[1][i] - 1.0) < NekConstants::kNekZeroTol)
452  {
453  // Distant diagonal edge shared by all eta_x coordinate planes:
454  // the xi_y == -xi_z line
455  m_eta[0][i] = -1.0;
456  }
457  else if (fabs(m_xi[1][i] + m_xi[2][i]) < NekConstants::kNekZeroTol)
458  {
459  m_eta[0][i] = -1.0;
460  }
461  else
462  {
463  m_eta[0][i] =
464  2.0 * (1.0 + m_xi[0][i]) / (-m_xi[1][i] - m_xi[2][i]) - 1.0;
465  }
466  m_eta[1][i] = 2.0 * (1.0 + m_xi[1][i]) / (1.0 - m_xi[2][i]) - 1.0;
467  m_eta[2][i] = m_xi[2][i];
468  }
469  }
470 }
int m_degree
Degree of the nodal element.
Definition: NodalUtil.h:107
NodalUtil(int degree, int dim)
Set up the NodalUtil object.
Definition: NodalUtil.h:100
int m_numPoints
Total number of nodal points.
Definition: NodalUtil.h:109
Array< OneD, Array< OneD, NekDouble > > m_xi
Coordinates of the nodal points defining the basis.
Definition: NodalUtil.h:111
std::tuple< int, int, int > Mode
Definition: NodalUtil.h:215
Array< OneD, Array< OneD, NekDouble > > m_eta
Collapsed coordinates of the nodal points.
Definition: NodalUtil.h:234
std::vector< Mode > m_ordering
Mapping from the indexing of the basis to a continuous ordering.
Definition: NodalUtil.h:230
static const NekDouble kNekZeroTol

References Nektar::NekConstants::kNekZeroTol, Nektar::LibUtilities::NodalUtil::m_degree, m_eta, Nektar::LibUtilities::NodalUtil::m_numPoints, m_ordering, and Nektar::LibUtilities::NodalUtil::m_xi.

◆ ~NodalUtilTetrahedron()

virtual Nektar::LibUtilities::NodalUtilTetrahedron::~NodalUtilTetrahedron ( )
inlinevirtual

Definition at line 223 of file NodalUtil.h.

224  {
225  }

Member Function Documentation

◆ v_CreateUtil()

virtual std::shared_ptr<NodalUtil> Nektar::LibUtilities::NodalUtilTetrahedron::v_CreateUtil ( Array< OneD, Array< OneD, NekDouble >> &  xi)
inlineoverrideprotectedvirtual

Construct a NodalUtil object of the appropriate element type for a given set of points.

This function is used inside NodalUtil::GetInterpolationMatrix so that the (potentially non-square) Vandermonde matrix can be constructed to create the interpolation matrix at an arbitrary set of points in the domain.

Parameters
xiDistribution of nodal points to create utility with.

Implements Nektar::LibUtilities::NodalUtil.

Definition at line 240 of file NodalUtil.h.

242  {
244  m_degree, xi[0], xi[1], xi[2]);
245  }
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.

References Nektar::MemoryManager< DataType >::AllocateSharedPtr(), and Nektar::LibUtilities::NodalUtil::m_degree.

◆ v_ModeZeroIntegral()

virtual NekDouble Nektar::LibUtilities::NodalUtilTetrahedron::v_ModeZeroIntegral ( )
inlineoverrideprotectedvirtual

Return the value of the integral of the zero-th mode for this element.

Note that for the orthogonal basis under consideration, all modes integrate to zero asides from the zero-th mode. This function is used in NodalUtil::GetWeights to determine integration weights.

Implements Nektar::LibUtilities::NodalUtil.

Definition at line 247 of file NodalUtil.h.

248  {
249  return 8.0 * sqrt(2.0) / 3.0;
250  }
scalarT< T > sqrt(scalarT< T > in)
Definition: scalar.hpp:294

References tinysimd::sqrt().

◆ v_NumModes()

virtual int Nektar::LibUtilities::NodalUtilTetrahedron::v_NumModes ( )
inlineoverrideprotectedvirtual

Calculate the number of degrees of freedom for this element.

Implements Nektar::LibUtilities::NodalUtil.

Definition at line 252 of file NodalUtil.h.

253  {
254  return (m_degree + 1) * (m_degree + 2) * (m_degree + 3) / 6;
255  }

References Nektar::LibUtilities::NodalUtil::m_degree.

◆ v_OrthoBasis()

NekVector< NekDouble > Nektar::LibUtilities::NodalUtilTetrahedron::v_OrthoBasis ( const int  mode)
overrideprotectedvirtual

Return the value of the modal functions for the tetrahedral element at the nodal points m_xi for a given mode.

In a tetrahedron, we use the orthogonal basis

\[ \psi_{m(ijk)} = \sqrt{8} P^{(0,0)}_i(\xi_1) P_j^{(2i+1,0)}(\xi_2) P_k^{(2i+2j+2,0)}(\xi_3) (1-\xi_2)^i (1-\xi_3)^{i+j} \]

where \( m(ijk) \) is the mapping defined in m_ordering and \( J_n^{(\alpha,\beta)}(z) \) denotes the standard Jacobi polynomial.

Parameters
modeThe mode of the orthogonal basis to evaluate.
Returns
Vector containing orthogonal basis evaluated at the points m_xi.

Implements Nektar::LibUtilities::NodalUtil.

Definition at line 488 of file NodalUtil.cpp.

489 {
490  std::vector<NekDouble> jacA(m_numPoints), jacB(m_numPoints);
491  std::vector<NekDouble> jacC(m_numPoints);
492 
493  int I, J, K;
494  std::tie(I, J, K) = m_ordering[mode];
495 
496  // Calculate Jacobi polynomials
497  Polylib::jacobfd(m_numPoints, &m_eta[0][0], &jacA[0], NULL, I, 0.0, 0.0);
498  Polylib::jacobfd(m_numPoints, &m_eta[1][0], &jacB[0], NULL, J,
499  2.0 * I + 1.0, 0.0);
500  Polylib::jacobfd(m_numPoints, &m_eta[2][0], &jacC[0], NULL, K,
501  2.0 * (I + J) + 2.0, 0.0);
502 
503  NekVector<NekDouble> ret(m_numPoints);
504  NekDouble sqrt8 = sqrt(8.0);
505 
506  for (int i = 0; i < m_numPoints; ++i)
507  {
508  ret[i] = sqrt8 * jacA[i] * jacB[i] * jacC[i] *
509  pow(1.0 - m_eta[1][i], I) * pow(1.0 - m_eta[2][i], I + J);
510  }
511 
512  return ret;
513 }
double NekDouble
void jacobfd(const int np, const double *z, double *poly_in, double *polyd, const int n, const double alpha, const double beta)
Routine to calculate Jacobi polynomials, , and their first derivative, .
Definition: Polylib.cpp:1181

References Polylib::jacobfd(), m_eta, Nektar::LibUtilities::NodalUtil::m_numPoints, m_ordering, and tinysimd::sqrt().

◆ v_OrthoBasisDeriv()

NekVector< NekDouble > Nektar::LibUtilities::NodalUtilTetrahedron::v_OrthoBasisDeriv ( const int  dir,
const int  mode 
)
overrideprotectedvirtual

Return the value of the derivative of the modal functions for the tetrahedral element at the nodal points m_xi for a given mode.

Note that this routine must use the chain rule combined with the collapsed coordinate derivatives as described in Sherwin & Karniadakis (2nd edition), pg 152.

Parameters
dirCoordinate direction in which to evaluate the derivative.
modeThe mode of the orthogonal basis to evaluate.
Returns
Vector containing the derivative of the orthogonal basis evaluated at the points m_xi.

Implements Nektar::LibUtilities::NodalUtil.

Definition at line 529 of file NodalUtil.cpp.

531 {
532  std::vector<NekDouble> jacA(m_numPoints), jacB(m_numPoints);
533  std::vector<NekDouble> jacC(m_numPoints);
534  std::vector<NekDouble> jacDerivA(m_numPoints), jacDerivB(m_numPoints);
535  std::vector<NekDouble> jacDerivC(m_numPoints);
536 
537  int I, J, K;
538  std::tie(I, J, K) = m_ordering[mode];
539 
540  // Calculate Jacobi polynomials
541  Polylib::jacobfd(m_numPoints, &m_eta[0][0], &jacA[0], NULL, I, 0.0, 0.0);
542  Polylib::jacobfd(m_numPoints, &m_eta[1][0], &jacB[0], NULL, J,
543  2.0 * I + 1.0, 0.0);
544  Polylib::jacobfd(m_numPoints, &m_eta[2][0], &jacC[0], NULL, K,
545  2.0 * (I + J) + 2.0, 0.0);
546  Polylib::jacobd(m_numPoints, &m_eta[0][0], &jacDerivA[0], I, 0.0, 0.0);
547  Polylib::jacobd(m_numPoints, &m_eta[1][0], &jacDerivB[0], J, 2.0 * I + 1.0,
548  0.0);
549  Polylib::jacobd(m_numPoints, &m_eta[2][0], &jacDerivC[0], K,
550  2.0 * (I + J) + 2.0, 0.0);
551 
552  NekVector<NekDouble> ret(m_numPoints);
553  NekDouble sqrt8 = sqrt(8.0);
554 
555  // Always compute x-derivative since this term appears in the latter two
556  // terms.
557  for (int i = 0; i < m_numPoints; ++i)
558  {
559  ret[i] = 4.0 * sqrt8 * jacDerivA[i] * jacB[i] * jacC[i];
560 
561  if (I > 0)
562  {
563  ret[i] *= pow(1 - m_eta[1][i], I - 1);
564  }
565 
566  if (I + J > 0)
567  {
568  ret[i] *= pow(1 - m_eta[2][i], I + J - 1);
569  }
570  }
571 
572  if (dir >= 1)
573  {
574  // Multiply by (1+a)/2
575  NekVector<NekDouble> tmp(m_numPoints);
576 
577  for (int i = 0; i < m_numPoints; ++i)
578  {
579  ret[i] *= 0.5 * (m_eta[0][i] + 1.0);
580 
581  tmp[i] = 2.0 * sqrt8 * jacA[i] * jacC[i];
582  if (I + J > 0)
583  {
584  tmp[i] *= pow(1.0 - m_eta[2][i], I + J - 1);
585  }
586 
587  NekDouble tmp2 = jacDerivB[i] * pow(1.0 - m_eta[1][i], I);
588  if (I > 0)
589  {
590  tmp2 -= I * jacB[i] * pow(1.0 - m_eta[1][i], I - 1);
591  }
592 
593  tmp[i] *= tmp2;
594  }
595 
596  if (dir == 1)
597  {
598  ret += tmp;
599  return ret;
600  }
601 
602  for (int i = 0; i < m_numPoints; ++i)
603  {
604  ret[i] += 0.5 * (1.0 + m_eta[1][i]) * tmp[i];
605 
606  NekDouble tmp2 = jacDerivC[i] * pow(1.0 - m_eta[2][i], I + J);
607  if (I + J > 0)
608  {
609  tmp2 -= jacC[i] * (I + J) * pow(1.0 - m_eta[2][i], I + J - 1);
610  }
611 
612  ret[i] +=
613  sqrt8 * jacA[i] * jacB[i] * pow(1.0 - m_eta[1][i], I) * tmp2;
614  }
615  }
616 
617  return ret;
618 }
void jacobd(const int np, const double *z, double *polyd, const int n, const double alpha, const double beta)
Calculate the derivative of Jacobi polynomials.
Definition: Polylib.cpp:1293

References Polylib::jacobd(), Polylib::jacobfd(), m_eta, Nektar::LibUtilities::NodalUtil::m_numPoints, m_ordering, and tinysimd::sqrt().

Member Data Documentation

◆ m_eta

Array<OneD, Array<OneD, NekDouble> > Nektar::LibUtilities::NodalUtilTetrahedron::m_eta
protected

Collapsed coordinates \( (\eta_1, \eta_2, \eta_3) \) of the nodal points.

Definition at line 234 of file NodalUtil.h.

Referenced by NodalUtilTetrahedron(), v_OrthoBasis(), and v_OrthoBasisDeriv().

◆ m_ordering

std::vector<Mode> Nektar::LibUtilities::NodalUtilTetrahedron::m_ordering
protected

Mapping from the \( (i,j,k) \) indexing of the basis to a continuous ordering.

Definition at line 230 of file NodalUtil.h.

Referenced by NodalUtilTetrahedron(), v_OrthoBasis(), and v_OrthoBasisDeriv().