Nektar++
NodalUtil.h
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File: NodalUtil.h
4 //
5 // For more information, please see: http://www.nektar.info
6 //
7 // The MIT License
8 //
9 // Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10 // Department of Aeronautics, Imperial College London (UK), and Scientific
11 // Computing and Imaging Institute, University of Utah (USA).
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining a
14 // copy of this software and associated documentation files (the "Software"),
15 // to deal in the Software without restriction, including without limitation
16 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 // and/or sell copies of the Software, and to permit persons to whom the
18 // Software is furnished to do so, subject to the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be included
21 // in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 // DEALINGS IN THE SOFTWARE.
30 //
31 // Description: 2D and 3D Nodal Triangle and Tetrahedron Utilities header file
32 // Basis function, Interpolation, Integral, Derivation, etc.
33 //
34 ///////////////////////////////////////////////////////////////////////////////
35 
36 #ifndef NODALUTIL_H
37 #define NODALUTIL_H
38 
39 #include <tuple>
40 
46 
48 
49 namespace Nektar
50 {
51 namespace LibUtilities
52 {
53 
54 typedef std::shared_ptr<NekMatrix<NekDouble>> SharedMatrix;
55 
56 /**
57  * @brief A class to assist in the construction of nodal simplex and hybrid
58  * elements in two and three dimensions.
59  *
60  * The NodalUtil class and its subclasses are designed to take care of some
61  * common issues that arise when considering triangles, tetrahedra and prismatic
62  * elements that are equipped with a nodal Lagrangian basis, defined using a set
63  * of nodal points \f$ \xi_i \f$ that we store in the array
64  * NodalUtil::m_xi. Since one cannot write this basis analytically, we instead
65  * construct the Vandermonde matrix
66  *
67  * \f[ \mathbf{V}_{ij} = \psi_j(\xi_i) \f]
68  *
69  * where \f$ \psi_j \f$ is a basis that spans the polynomial space of the
70  * element. The Vandermonde matrix can then be used to construct the integration
71  * weights, derivative and interpolation matrices. Although this can be any
72  * basis, such as the monomial basis \f$ x^i y^j z^k \f$, in practice this is
73  * numerically unstable at high polynomial orders. Elements are therefore
74  * expected to use the 'traditional' modal orthogonal basis. See Sherwin &
75  * Karniadakis or Hesthaven & Warburton for further details of this basis and
76  * the surrounding numerical issues.
77  *
78  * This class therefore contains the generic logic needed to construct various
79  * matrices, and subclasses override virtual functions that define the
80  * orthogonal basis and its derivatives for a particular element type.
81  */
82 class NodalUtil
83 {
84 public:
85  LIB_UTILITIES_EXPORT virtual ~NodalUtil() = default;
92 
93 protected:
94  /**
95  * @brief Set up the NodalUtil object.
96  *
97  * @param dim Dimension of the element.
98  * @param degree Polynomial degree of the element.
99  */
100  NodalUtil(int degree, int dim) : m_dim(dim), m_degree(degree), m_xi(dim)
101  {
102  }
103 
104  /// Dimension of the nodal element
105  int m_dim;
106  /// Degree of the nodal element
107  int m_degree;
108  /// Total number of nodal points
110  /// Coordinates of the nodal points defining the basis
112 
113  /**
114  * @brief Return the values of the orthogonal basis at the nodal points for
115  * a given mode.
116  *
117  * @param mode Mode number, which is between 0 and NodalUtil::v_NumModes()
118  * - 1.
119  *
120  * @return Orthogonal mode @p mode evaluated at the nodal points.
121  */
122  virtual NekVector<NekDouble> v_OrthoBasis(const int mode) = 0;
123 
124  /**
125  * @brief Return the values of the derivative of the orthogonal basis at the
126  * nodal points for a given mode.
127  *
128  * @param dir Coordinate direction of derivative.
129  * @param mode Mode number, which is between 0 and NodalUtil::v_NumModes()
130  * - 1.
131  */
133  const int mode) = 0;
134 
135  /**
136  * @brief Construct a NodalUtil object of the appropriate element type for a
137  * given set of points.
138  *
139  * This function is used inside NodalUtil::GetInterpolationMatrix so that
140  * the (potentially non-square) Vandermonde matrix can be constructed to
141  * create the interpolation matrix at an arbitrary set of points in the
142  * domain.
143  *
144  * @param xi Distribution of nodal points to create utility with.
145  */
146  virtual std::shared_ptr<NodalUtil> v_CreateUtil(
147  Array<OneD, Array<OneD, NekDouble>> &xi) = 0;
148 
149  /**
150  * @brief Return the value of the integral of the zero-th mode for this
151  * element.
152  *
153  * Note that for the orthogonal basis under consideration, all modes
154  * integrate to zero asides from the zero-th mode. This function is used in
155  * NodalUtil::GetWeights to determine integration weights.
156  */
158 
159  /**
160  * @brief Calculate the number of degrees of freedom for this element.
161  */
162  virtual int v_NumModes() = 0;
163 };
164 
165 /**
166  * @brief Specialisation of the NodalUtil class to support nodal triangular
167  * elements.
168  */
170 {
171 public:
174 
176  {
177  }
178 
179 protected:
180  /// Mapping from the \f$ (i,j) \f$ indexing of the basis to a continuous
181  /// ordering.
182  std::vector<std::pair<int, int>> m_ordering;
183 
184  /// Collapsed coordinates \f$ (\eta_1, \eta_2) \f$ of the nodal points.
186 
187  virtual NekVector<NekDouble> v_OrthoBasis(const int mode) override;
188  virtual NekVector<NekDouble> v_OrthoBasisDeriv(const int dir,
189  const int mode) override;
190 
191  virtual std::shared_ptr<NodalUtil> v_CreateUtil(
192  Array<OneD, Array<OneD, NekDouble>> &xi) override
193  {
195  m_degree, xi[0], xi[1]);
196  }
197 
198  virtual NekDouble v_ModeZeroIntegral() override
199  {
200  return 2.0 * sqrt(2.0);
201  }
202 
203  virtual int v_NumModes() override
204  {
205  return (m_degree + 1) * (m_degree + 2) / 2;
206  }
207 };
208 
209 /**
210  * @brief Specialisation of the NodalUtil class to support nodal tetrahedral
211  * elements.
212  */
214 {
215  typedef std::tuple<int, int, int> Mode;
216 
217 public:
222 
224  {
225  }
226 
227 protected:
228  /// Mapping from the \f$ (i,j,k) \f$ indexing of the basis to a continuous
229  /// ordering.
230  std::vector<Mode> m_ordering;
231 
232  /// Collapsed coordinates \f$ (\eta_1, \eta_2, \eta_3) \f$ of the nodal
233  /// points.
235 
236  virtual NekVector<NekDouble> v_OrthoBasis(const int mode) override;
237  virtual NekVector<NekDouble> v_OrthoBasisDeriv(const int dir,
238  const int mode) override;
239 
240  virtual std::shared_ptr<NodalUtil> v_CreateUtil(
241  Array<OneD, Array<OneD, NekDouble>> &xi) override
242  {
244  m_degree, xi[0], xi[1], xi[2]);
245  }
246 
247  virtual NekDouble v_ModeZeroIntegral() override
248  {
249  return 8.0 * sqrt(2.0) / 3.0;
250  }
251 
252  virtual int v_NumModes() override
253  {
254  return (m_degree + 1) * (m_degree + 2) * (m_degree + 3) / 6;
255  }
256 };
257 
258 /**
259  * @brief Specialisation of the NodalUtil class to support nodal prismatic
260  * elements.
261  */
262 class NodalUtilPrism : public NodalUtil
263 {
264  typedef std::tuple<int, int, int> Mode;
265 
266 public:
270 
272  {
273  }
274 
275 protected:
276  /// Mapping from the \f$ (i,j) \f$ indexing of the basis to a continuous
277  /// ordering.
278  std::vector<Mode> m_ordering;
279 
280  /// Collapsed coordinates \f$ (\eta_1, \eta_2, \eta_3) \f$ of the nodal
281  /// points.
283 
284  virtual NekVector<NekDouble> v_OrthoBasis(const int mode) override;
285  virtual NekVector<NekDouble> v_OrthoBasisDeriv(const int dir,
286  const int mode) override;
287 
288  virtual std::shared_ptr<NodalUtil> v_CreateUtil(
289  Array<OneD, Array<OneD, NekDouble>> &xi) override
290  {
292  xi[1], xi[2]);
293  }
294 
295  virtual NekDouble v_ModeZeroIntegral() override
296  {
297  return 4.0 * sqrt(2.0);
298  }
299 
300  virtual int v_NumModes() override
301  {
302  return (m_degree + 1) * (m_degree + 1) * (m_degree + 2) / 2;
303  }
304 };
305 
306 /**
307  * @brief Specialisation of the NodalUtil class to support nodal quad elements.
308  */
309 class NodalUtilQuad : public NodalUtil
310 {
311 public:
314 
316  {
317  }
318 
319 protected:
320  /// Mapping from the \f$ (i,j) \f$ indexing of the basis to a continuous
321  /// ordering.
322  std::vector<std::pair<int, int>> m_ordering;
323 
324  virtual NekVector<NekDouble> v_OrthoBasis(const int mode) override;
325  virtual NekVector<NekDouble> v_OrthoBasisDeriv(const int dir,
326  const int mode) override;
327 
328  virtual std::shared_ptr<NodalUtil> v_CreateUtil(
329  Array<OneD, Array<OneD, NekDouble>> &xi) override
330  {
332  xi[1]);
333  }
334 
335  virtual NekDouble v_ModeZeroIntegral() override
336  {
337  return 4.0;
338  }
339 
340  virtual int v_NumModes() override
341  {
342  return (m_degree + 1) * (m_degree + 1);
343  }
344 };
345 
346 /**
347  * @brief Specialisation of the NodalUtil class to support nodal hex elements.
348  */
349 class NodalUtilHex : public NodalUtil
350 {
351  typedef std::tuple<int, int, int> Mode;
352 
353 public:
357 
359  {
360  }
361 
362 protected:
363  /// Mapping from the \f$ (i,j,k) \f$ indexing of the basis to a continuous
364  /// ordering.
365  std::vector<Mode> m_ordering;
366 
367  virtual NekVector<NekDouble> v_OrthoBasis(const int mode) override;
368  virtual NekVector<NekDouble> v_OrthoBasisDeriv(const int dir,
369  const int mode) override;
370 
371  virtual std::shared_ptr<NodalUtil> v_CreateUtil(
372  Array<OneD, Array<OneD, NekDouble>> &xi) override
373  {
375  xi[1], xi[2]);
376  }
377 
378  virtual NekDouble v_ModeZeroIntegral() override
379  {
380  return 8.0;
381  }
382 
383  virtual int v_NumModes() override
384  {
385  return (m_degree + 1) * (m_degree + 1) * (m_degree + 1);
386  }
387 };
388 
389 } // namespace LibUtilities
390 } // namespace Nektar
391 
392 #endif // NODALUTIL_H
#define LIB_UTILITIES_EXPORT
Specialisation of the NodalUtil class to support nodal hex elements.
Definition: NodalUtil.h:350
virtual NekVector< NekDouble > v_OrthoBasisDeriv(const int dir, const int mode) override
Return the values of the derivative of the orthogonal basis at the nodal points for a given mode.
Definition: NodalUtil.cpp:996
virtual std::shared_ptr< NodalUtil > v_CreateUtil(Array< OneD, Array< OneD, NekDouble >> &xi) override
Construct a NodalUtil object of the appropriate element type for a given set of points.
Definition: NodalUtil.h:371
virtual NekVector< NekDouble > v_OrthoBasis(const int mode) override
Return the value of the modal functions for the hex element at the nodal points m_xi for a given mode...
Definition: NodalUtil.cpp:973
virtual int v_NumModes() override
Calculate the number of degrees of freedom for this element.
Definition: NodalUtil.h:383
NodalUtilHex(int degree, Array< OneD, NekDouble > r, Array< OneD, NekDouble > s, Array< OneD, NekDouble > t)
Construct the nodal utility class for a hexahedron.
Definition: NodalUtil.cpp:937
std::vector< Mode > m_ordering
Mapping from the indexing of the basis to a continuous ordering.
Definition: NodalUtil.h:365
std::tuple< int, int, int > Mode
Definition: NodalUtil.h:351
virtual NekDouble v_ModeZeroIntegral() override
Return the value of the integral of the zero-th mode for this element.
Definition: NodalUtil.h:378
A class to assist in the construction of nodal simplex and hybrid elements in two and three dimension...
Definition: NodalUtil.h:83
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
virtual std::shared_ptr< NodalUtil > v_CreateUtil(Array< OneD, Array< OneD, NekDouble >> &xi)=0
Construct a NodalUtil object of the appropriate element type for a given set of points.
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
NekVector< NekDouble > GetWeights()
Obtain the integration weights for the given nodal distribution.
Definition: NodalUtil.cpp:65
SharedMatrix GetVandermonde()
Return the Vandermonde matrix for the nodal distribution.
Definition: NodalUtil.cpp:101
SharedMatrix GetVandermondeForDeriv(int dir)
Return the Vandermonde matrix of the derivative of the basis functions for the nodal distribution.
Definition: NodalUtil.cpp:134
virtual int v_NumModes()=0
Calculate the number of degrees of freedom for this element.
SharedMatrix GetDerivMatrix(int dir)
Return the derivative matrix for the nodal distribution.
Definition: NodalUtil.cpp:167
int m_dim
Dimension of the nodal element.
Definition: NodalUtil.h:105
virtual NekDouble v_ModeZeroIntegral()=0
Return the value of the integral of the zero-th mode for this element.
virtual NekVector< NekDouble > v_OrthoBasisDeriv(const int dir, const int mode)=0
Return the values of the derivative of the orthogonal basis at the nodal points for a given mode.
SharedMatrix GetInterpolationMatrix(Array< OneD, Array< OneD, NekDouble >> &xi)
Construct the interpolation matrix used to evaluate the basis at the points xi inside the element.
Definition: NodalUtil.cpp:201
virtual NekVector< NekDouble > v_OrthoBasis(const int mode)=0
Return the values of the orthogonal basis at the nodal points for a given mode.
Specialisation of the NodalUtil class to support nodal prismatic elements.
Definition: NodalUtil.h:263
NodalUtilPrism(int degree, Array< OneD, NekDouble > r, Array< OneD, NekDouble > s, Array< OneD, NekDouble > t)
Construct the nodal utility class for a prism.
Definition: NodalUtil.cpp:645
virtual NekVector< NekDouble > v_OrthoBasisDeriv(const int dir, const int mode) override
Return the value of the derivative of the modal functions for the prismatic element at the nodal poin...
Definition: NodalUtil.cpp:747
virtual NekVector< NekDouble > v_OrthoBasis(const int mode) override
Return the value of the modal functions for the prismatic element at the nodal points m_xi for a give...
Definition: NodalUtil.cpp:707
virtual int v_NumModes() override
Calculate the number of degrees of freedom for this element.
Definition: NodalUtil.h:300
Array< OneD, Array< OneD, NekDouble > > m_eta
Collapsed coordinates of the nodal points.
Definition: NodalUtil.h:282
virtual std::shared_ptr< NodalUtil > v_CreateUtil(Array< OneD, Array< OneD, NekDouble >> &xi) override
Construct a NodalUtil object of the appropriate element type for a given set of points.
Definition: NodalUtil.h:288
std::vector< Mode > m_ordering
Mapping from the indexing of the basis to a continuous ordering.
Definition: NodalUtil.h:278
virtual NekDouble v_ModeZeroIntegral() override
Return the value of the integral of the zero-th mode for this element.
Definition: NodalUtil.h:295
std::tuple< int, int, int > Mode
Definition: NodalUtil.h:264
Specialisation of the NodalUtil class to support nodal quad elements.
Definition: NodalUtil.h:310
virtual NekVector< NekDouble > v_OrthoBasisDeriv(const int dir, const int mode) override
Return the value of the derivative of the modal functions for the quadrilateral element at the nodal ...
Definition: NodalUtil.cpp:886
NodalUtilQuad(int degree, Array< OneD, NekDouble > r, Array< OneD, NekDouble > s)
Construct the nodal utility class for a quadrilateral.
Definition: NodalUtil.cpp:826
virtual NekDouble v_ModeZeroIntegral() override
Return the value of the integral of the zero-th mode for this element.
Definition: NodalUtil.h:335
virtual std::shared_ptr< NodalUtil > v_CreateUtil(Array< OneD, Array< OneD, NekDouble >> &xi) override
Construct a NodalUtil object of the appropriate element type for a given set of points.
Definition: NodalUtil.h:328
virtual int v_NumModes() override
Calculate the number of degrees of freedom for this element.
Definition: NodalUtil.h:340
std::vector< std::pair< int, int > > m_ordering
Mapping from the indexing of the basis to a continuous ordering.
Definition: NodalUtil.h:322
virtual NekVector< NekDouble > v_OrthoBasis(const int mode) override
Return the value of the modal functions for the quad element at the nodal points m_xi for a given mod...
Definition: NodalUtil.cpp:859
Specialisation of the NodalUtil class to support nodal tetrahedral elements.
Definition: NodalUtil.h:214
virtual int v_NumModes() override
Calculate the number of degrees of freedom for this element.
Definition: NodalUtil.h:252
virtual std::shared_ptr< NodalUtil > v_CreateUtil(Array< OneD, Array< OneD, NekDouble >> &xi) override
Construct a NodalUtil object of the appropriate element type for a given set of points.
Definition: NodalUtil.h:240
std::tuple< int, int, int > Mode
Definition: NodalUtil.h:215
virtual NekVector< NekDouble > v_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 po...
Definition: NodalUtil.cpp:529
Array< OneD, Array< OneD, NekDouble > > m_eta
Collapsed coordinates of the nodal points.
Definition: NodalUtil.h:234
NodalUtilTetrahedron(int degree, Array< OneD, NekDouble > r, Array< OneD, NekDouble > s, Array< OneD, NekDouble > t)
Construct the nodal utility class for a tetrahedron.
Definition: NodalUtil.cpp:414
std::vector< Mode > m_ordering
Mapping from the indexing of the basis to a continuous ordering.
Definition: NodalUtil.h:230
virtual NekVector< NekDouble > v_OrthoBasis(const int mode) override
Return the value of the modal functions for the tetrahedral element at the nodal points m_xi for a gi...
Definition: NodalUtil.cpp:488
virtual NekDouble v_ModeZeroIntegral() override
Return the value of the integral of the zero-th mode for this element.
Definition: NodalUtil.h:247
Specialisation of the NodalUtil class to support nodal triangular elements.
Definition: NodalUtil.h:170
NodalUtilTriangle(int degree, Array< OneD, NekDouble > r, Array< OneD, NekDouble > s)
Construct the nodal utility class for a triangle.
Definition: NodalUtil.cpp:238
virtual NekDouble v_ModeZeroIntegral() override
Return the value of the integral of the zero-th mode for this element.
Definition: NodalUtil.h:198
std::vector< std::pair< int, int > > m_ordering
Mapping from the indexing of the basis to a continuous ordering.
Definition: NodalUtil.h:182
virtual NekVector< NekDouble > v_OrthoBasisDeriv(const int dir, const int mode) override
Return the value of the derivative of the modal functions for the triangular element at the nodal poi...
Definition: NodalUtil.cpp:330
virtual NekVector< NekDouble > v_OrthoBasis(const int mode) override
Return the value of the modal functions for the triangular element at the nodal points m_xi for a giv...
Definition: NodalUtil.cpp:293
virtual std::shared_ptr< NodalUtil > v_CreateUtil(Array< OneD, Array< OneD, NekDouble >> &xi) override
Construct a NodalUtil object of the appropriate element type for a given set of points.
Definition: NodalUtil.h:191
virtual int v_NumModes() override
Calculate the number of degrees of freedom for this element.
Definition: NodalUtil.h:203
Array< OneD, Array< OneD, NekDouble > > m_eta
Collapsed coordinates of the nodal points.
Definition: NodalUtil.h:185
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
std::shared_ptr< NekMatrix< NekDouble > > SharedMatrix
Definition: NodalUtil.h:54
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
double NekDouble
scalarT< T > sqrt(scalarT< T > in)
Definition: scalar.hpp:294