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
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)
 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)
 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)
 Construct a NodalUtil object of the appropriate element type for a given set of points. More...
 
virtual NekDouble v_ModeZeroIntegral ()
 Return the value of the integral of the zero-th mode for this element. More...
 
virtual int v_NumModes ()
 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 214 of file NodalUtil.h.

Member Typedef Documentation

◆ Mode

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

Definition at line 216 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 419 of file NodalUtil.cpp.

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

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

◆ ~NodalUtilTetrahedron()

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

Definition at line 224 of file NodalUtil.h.

225  {
226  }

Member Function Documentation

◆ v_CreateUtil()

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

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 241 of file NodalUtil.h.

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

243  {
245  m_degree, xi[0], xi[1], xi[2]);
246  }
int m_degree
Degree of the nodal element.
Definition: NodalUtil.h:107
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.

◆ v_ModeZeroIntegral()

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

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 248 of file NodalUtil.h.

249  {
250  return 8.0 * sqrt(2.0) / 3.0;
251  }

◆ v_NumModes()

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

Calculate the number of degrees of freedom for this element.

Implements Nektar::LibUtilities::NodalUtil.

Definition at line 253 of file NodalUtil.h.

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

254  {
255  return (m_degree + 1) * (m_degree + 2) * (m_degree + 3) / 6;
256  }
int m_degree
Degree of the nodal element.
Definition: NodalUtil.h:107

◆ v_OrthoBasis()

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

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 494 of file NodalUtil.cpp.

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

495 {
496  std::vector<NekDouble> jacA(m_numPoints), jacB(m_numPoints);
497  std::vector<NekDouble> jacC(m_numPoints);
498 
499  int I, J, K;
500  std::tie(I, J, K) = m_ordering[mode];
501 
502  // Calculate Jacobi polynomials
504  m_numPoints, &m_eta[0][0], &jacA[0], NULL, I, 0.0, 0.0);
506  m_numPoints, &m_eta[1][0], &jacB[0], NULL, J, 2.0 * I + 1.0, 0.0);
508  m_numPoints, &m_eta[2][0], &jacC[0], NULL, K, 2.0 * (I+J) + 2.0, 0.0);
509 
510  NekVector<NekDouble> ret(m_numPoints);
511  NekDouble sqrt8 = sqrt(8.0);
512 
513  for (int i = 0; i < m_numPoints; ++i)
514  {
515  ret[i] = sqrt8 * jacA[i] * jacB[i] * jacC[i] *
516  pow(1.0 - m_eta[1][i], I) * pow(1.0 - m_eta[2][i], I + J);
517  }
518 
519  return ret;
520 }
std::vector< Mode > m_ordering
Mapping from the indexing of the basis to a continuous ordering.
Definition: NodalUtil.h:231
Array< OneD, Array< OneD, NekDouble > > m_eta
Collapsed coordinates of the nodal points.
Definition: NodalUtil.h:235
double NekDouble
int m_numPoints
Total number of nodal points.
Definition: NodalUtil.h:109
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:1031

◆ v_OrthoBasisDeriv()

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

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 536 of file NodalUtil.cpp.

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

538 {
539  std::vector<NekDouble> jacA(m_numPoints), jacB(m_numPoints);
540  std::vector<NekDouble> jacC(m_numPoints);
541  std::vector<NekDouble> jacDerivA(m_numPoints), jacDerivB(m_numPoints);
542  std::vector<NekDouble> jacDerivC(m_numPoints);
543 
544  int I, J, K;
545  std::tie(I, J, K) = m_ordering[mode];
546 
547  // Calculate Jacobi polynomials
549  m_numPoints, &m_eta[0][0], &jacA[0], NULL, I, 0.0, 0.0);
551  m_numPoints, &m_eta[1][0], &jacB[0], NULL, J, 2.0 * I + 1.0, 0.0);
553  m_numPoints, &m_eta[2][0], &jacC[0], NULL, K, 2.0 * (I+J) + 2.0, 0.0);
555  m_numPoints, &m_eta[0][0], &jacDerivA[0], I, 0.0, 0.0);
557  m_numPoints, &m_eta[1][0], &jacDerivB[0], J, 2.0 * I + 1.0, 0.0);
559  m_numPoints, &m_eta[2][0], &jacDerivC[0], K, 2.0 * (I+J) + 2.0, 0.0);
560 
561  NekVector<NekDouble> ret(m_numPoints);
562  NekDouble sqrt8 = sqrt(8.0);
563 
564  // Always compute x-derivative since this term appears in the latter two
565  // terms.
566  for (int i = 0; i < m_numPoints; ++i)
567  {
568  ret[i] = 4.0 * sqrt8 * jacDerivA[i] * jacB[i] * jacC[i];
569 
570  if (I > 0)
571  {
572  ret[i] *= pow(1 - m_eta[1][i], I - 1);
573  }
574 
575  if (I + J > 0)
576  {
577  ret[i] *= pow(1 - m_eta[2][i], I + J - 1);
578  }
579  }
580 
581  if (dir >= 1)
582  {
583  // Multiply by (1+a)/2
584  NekVector<NekDouble> tmp(m_numPoints);
585 
586  for (int i = 0; i < m_numPoints; ++i)
587  {
588  ret[i] *= 0.5 * (m_eta[0][i] + 1.0);
589 
590  tmp[i] = 2.0 * sqrt8 * jacA[i] * jacC[i];
591  if (I + J > 0)
592  {
593  tmp[i] *= pow(1.0 - m_eta[2][i], I + J - 1);
594  }
595 
596  NekDouble tmp2 = jacDerivB[i] * pow(1.0 - m_eta[1][i], I);
597  if (I > 0)
598  {
599  tmp2 -= I * jacB[i] * pow(1.0 - m_eta[1][i], I - 1);
600  }
601 
602  tmp[i] *= tmp2;
603  }
604 
605  if (dir == 1)
606  {
607  ret += tmp;
608  return ret;
609  }
610 
611  for (int i = 0; i < m_numPoints; ++i)
612  {
613  ret[i] += 0.5 * (1.0 + m_eta[1][i]) * tmp[i];
614 
615  NekDouble tmp2 = jacDerivC[i] * pow(1.0 - m_eta[2][i], I + J);
616  if (I + J > 0)
617  {
618  tmp2 -= jacC[i] * (I + J) * pow(1.0 - m_eta[2][i], I + J - 1);
619  }
620 
621  ret[i] += sqrt8 * jacA[i] * jacB[i] * pow(1.0 - m_eta[1][i], I) *
622  tmp2;
623  }
624  }
625 
626  return ret;
627 }
std::vector< Mode > m_ordering
Mapping from the indexing of the basis to a continuous ordering.
Definition: NodalUtil.h:231
Array< OneD, Array< OneD, NekDouble > > m_eta
Collapsed coordinates of the nodal points.
Definition: NodalUtil.h:235
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:1131
double NekDouble
int m_numPoints
Total number of nodal points.
Definition: NodalUtil.h:109
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:1031

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 235 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 231 of file NodalUtil.h.

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