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 
50 namespace Nektar
51 {
52 namespace LibUtilities
53 {
54 
55 typedef std::shared_ptr<NekMatrix<NekDouble> > SharedMatrix;
56 
57 /**
58  * @brief A class to assist in the construction of nodal simplex and hybrid
59  * elements in two and three dimensions.
60  *
61  * The NodalUtil class and its subclasses are designed to take care of some
62  * common issues that arise when considering triangles, tetrahedra and prismatic
63  * elements that are equipped with a nodal Lagrangian basis, defined using a set
64  * of nodal points \f$ \xi_i \f$ that we store in the array
65  * NodalUtil::m_xi. Since one cannot write this basis analytically, we instead
66  * construct the Vandermonde matrix
67  *
68  * \f[ \mathbf{V}_{ij} = \psi_j(\xi_i) \f]
69  *
70  * where \f$ \psi_j \f$ is a basis that spans the polynomial space of the
71  * element. The Vandermonde matrix can then be used to construct the integration
72  * weights, derivative and interpolation matrices. Although this can be any
73  * basis, such as the monomial basis \f$ x^i y^j z^k \f$, in practice this is
74  * numerically unstable at high polynomial orders. Elements are therefore
75  * expected to use the 'traditional' modal orthogonal basis. See Sherwin &
76  * Karniadakis or Hesthaven & Warburton for further details of this basis and
77  * the surrounding numerical issues.
78  *
79  * This class therefore contains the generic logic needed to construct various
80  * matrices, and subclasses override virtual functions that define the
81  * orthogonal basis and its derivatives for a particular element type.
82  */
83 class NodalUtil
84 {
85 public:
87  LIB_UTILITIES_EXPORT SharedMatrix GetVandermonde();
88  LIB_UTILITIES_EXPORT SharedMatrix GetVandermondeForDeriv(int dir);
89  LIB_UTILITIES_EXPORT SharedMatrix GetDerivMatrix(int dir);
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 dir, 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  */
157  virtual NekDouble v_ModeZeroIntegral() = 0;
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:
175 
177  {
178  }
179 
180 protected:
181  /// Mapping from the \f$ (i,j) \f$ indexing of the basis to a continuous
182  /// ordering.
183  std::vector<std::pair<int, int> > m_ordering;
184 
185  /// Collapsed coordinates \f$ (\eta_1, \eta_2) \f$ of the nodal points.
187 
188  virtual NekVector<NekDouble> v_OrthoBasis(const int mode);
190  const int dir, const int mode);
191 
192  virtual std::shared_ptr<NodalUtil> v_CreateUtil(
194  {
196  m_degree, xi[0], xi[1]);
197  }
198 
200  {
201  return 2.0 * sqrt(2.0);
202  }
203 
204  virtual int v_NumModes()
205  {
206  return (m_degree + 1) * (m_degree + 2) / 2;
207  }
208 };
209 
210 /**
211  * @brief Specialisation of the NodalUtil class to support nodal tetrahedral
212  * elements.
213  */
215 {
216  typedef std::tuple<int, int, int> Mode;
217 
218 public:
223 
225  {
226  }
227 
228 protected:
229  /// Mapping from the \f$ (i,j,k) \f$ indexing of the basis to a continuous
230  /// ordering.
231  std::vector<Mode> m_ordering;
232 
233  /// Collapsed coordinates \f$ (\eta_1, \eta_2, \eta_3) \f$ of the nodal
234  /// points.
236 
237  virtual NekVector<NekDouble> v_OrthoBasis(const int mode);
239  const int dir, const int mode);
240 
241  virtual std::shared_ptr<NodalUtil> v_CreateUtil(
243  {
245  m_degree, xi[0], xi[1], xi[2]);
246  }
247 
249  {
250  return 8.0 * sqrt(2.0) / 3.0;
251  }
252 
253  virtual int v_NumModes()
254  {
255  return (m_degree + 1) * (m_degree + 2) * (m_degree + 3) / 6;
256  }
257 };
258 
259 /**
260  * @brief Specialisation of the NodalUtil class to support nodal prismatic
261  * elements.
262  */
263 class NodalUtilPrism : public NodalUtil
264 {
265  typedef std::tuple<int, int, int> Mode;
266 
267 public:
272 
274  {
275  }
276 
277 protected:
278  /// Mapping from the \f$ (i,j) \f$ indexing of the basis to a continuous
279  /// ordering.
280  std::vector<Mode> m_ordering;
281 
282  /// Collapsed coordinates \f$ (\eta_1, \eta_2, \eta_3) \f$ of the nodal
283  /// points.
285 
286  virtual NekVector<NekDouble> v_OrthoBasis(const int mode);
288  const int dir, const int mode);
289 
290  virtual std::shared_ptr<NodalUtil> v_CreateUtil(
292  {
294  m_degree, xi[0], xi[1], xi[2]);
295  }
296 
298  {
299  return 4.0 * sqrt(2.0);
300  }
301 
302  virtual int v_NumModes()
303  {
304  return (m_degree + 1) * (m_degree + 1) * (m_degree + 2) / 2;
305  }
306 };
307 
308 /**
309  * @brief Specialisation of the NodalUtil class to support nodal quad elements.
310  */
311 class NodalUtilQuad : public NodalUtil
312 {
313 public:
317 
319  {
320  }
321 
322 protected:
323  /// Mapping from the \f$ (i,j) \f$ indexing of the basis to a continuous
324  /// ordering.
325  std::vector<std::pair<int, int> > m_ordering;
326 
327  virtual NekVector<NekDouble> v_OrthoBasis(const int mode);
329  const int dir, const int mode);
330 
331  virtual std::shared_ptr<NodalUtil> v_CreateUtil(
333  {
335  m_degree, xi[0], xi[1]);
336  }
337 
339  {
340  return 4.0;
341  }
342 
343  virtual int v_NumModes()
344  {
345  return (m_degree + 1) * (m_degree + 1);
346  }
347 };
348 
349 /**
350  * @brief Specialisation of the NodalUtil class to support nodal hex elements.
351  */
352 class NodalUtilHex : public NodalUtil
353 {
354  typedef std::tuple<int, int, int> Mode;
355 
356 public:
361 
363  {
364  }
365 
366 protected:
367  /// Mapping from the \f$ (i,j,k) \f$ indexing of the basis to a continuous
368  /// ordering.
369  std::vector<Mode> m_ordering;
370 
371  virtual NekVector<NekDouble> v_OrthoBasis(const int mode);
373  const int dir, const int mode);
374 
375  virtual std::shared_ptr<NodalUtil> v_CreateUtil(
377  {
379  m_degree, xi[0], xi[1], xi[2]);
380  }
381 
383  {
384  return 8.0;
385  }
386 
387  virtual int v_NumModes()
388  {
389  return (m_degree + 1) * (m_degree + 1) * (m_degree + 1);
390  }
391 };
392 
393 
394 }
395 }
396 
397 #endif //NODALUTIL_H
std::vector< Mode > m_ordering
Mapping from the indexing of the basis to a continuous ordering.
Definition: NodalUtil.h:231
virtual NekDouble v_ModeZeroIntegral()
Return the value of the integral of the zero-th mode for this element.
Definition: NodalUtil.h:297
std::tuple< int, int, int > Mode
Definition: NodalUtil.h:216
virtual int v_NumModes()
Calculate the number of degrees of freedom for this element.
Definition: NodalUtil.h:204
A class to assist in the construction of nodal simplex and hybrid elements in two and three dimension...
Definition: NodalUtil.h:83
Specialisation of the NodalUtil class to support nodal triangular elements.
Definition: NodalUtil.h:169
virtual std::shared_ptr< NodalUtil > v_CreateUtil(Array< OneD, Array< OneD, NekDouble > > &xi)
Construct a NodalUtil object of the appropriate element type for a given set of points.
Definition: NodalUtil.h:241
virtual NekDouble v_ModeZeroIntegral()
Return the value of the integral of the zero-th mode for this element.
Definition: NodalUtil.h:338
std::shared_ptr< NekMatrix< NekDouble > > SharedMatrix
Definition: NodalUtil.h:55
Array< OneD, Array< OneD, NekDouble > > m_eta
Collapsed coordinates of the nodal points.
Definition: NodalUtil.h:284
virtual std::shared_ptr< NodalUtil > v_CreateUtil(Array< OneD, Array< OneD, NekDouble > > &xi)
Construct a NodalUtil object of the appropriate element type for a given set of points.
Definition: NodalUtil.h:375
Array< OneD, Array< OneD, NekDouble > > m_eta
Collapsed coordinates of the nodal points.
Definition: NodalUtil.h:235
SharedMatrix GetVandermondeForDeriv(int dir)
Return the Vandermonde matrix of the derivative of the basis functions for the nodal distribution...
Definition: NodalUtil.cpp:134
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 NekDouble v_ModeZeroIntegral()
Return the value of the integral of the zero-th mode for this element.
Definition: NodalUtil.h:382
std::vector< std::pair< int, int > > m_ordering
Mapping from the indexing of the basis to a continuous ordering.
Definition: NodalUtil.h:183
std::tuple< int, int, int > Mode
Definition: NodalUtil.h:354
int m_degree
Degree of the nodal element.
Definition: NodalUtil.h:107
virtual std::shared_ptr< NodalUtil > v_CreateUtil(Array< OneD, Array< OneD, NekDouble > > &xi)
Construct a NodalUtil object of the appropriate element type for a given set of points.
Definition: NodalUtil.h:331
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.
#define LIB_UTILITIES_EXPORT
Specialisation of the NodalUtil class to support nodal hex elements.
Definition: NodalUtil.h:352
virtual NekDouble v_ModeZeroIntegral()
Return the value of the integral of the zero-th mode for this element.
Definition: NodalUtil.h:199
Array< OneD, Array< OneD, NekDouble > > m_eta
Collapsed coordinates of the nodal points.
Definition: NodalUtil.h:186
SharedMatrix GetDerivMatrix(int dir)
Return the derivative matrix for the nodal distribution.
Definition: NodalUtil.cpp:167
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
std::vector< Mode > m_ordering
Mapping from the indexing of the basis to a continuous ordering.
Definition: NodalUtil.h:369
virtual int v_NumModes()
Calculate the number of degrees of freedom for this element.
Definition: NodalUtil.h:302
NodalUtil(int degree, int dim)
Set up the NodalUtil object.
Definition: NodalUtil.h:100
double NekDouble
NekVector< NekDouble > GetWeights()
Obtain the integration weights for the given nodal distribution.
Definition: NodalUtil.cpp:65
virtual int v_NumModes()
Calculate the number of degrees of freedom for this element.
Definition: NodalUtil.h:387
virtual std::shared_ptr< NodalUtil > v_CreateUtil(Array< OneD, Array< OneD, NekDouble > > &xi)
Construct a NodalUtil object of the appropriate element type for a given set of points.
Definition: NodalUtil.h:290
std::tuple< int, int, int > Mode
Definition: NodalUtil.h:265
Specialisation of the NodalUtil class to support nodal prismatic elements.
Definition: NodalUtil.h:263
virtual int v_NumModes()
Calculate the number of degrees of freedom for this element.
Definition: NodalUtil.h:343
SharedMatrix GetVandermonde()
Return the Vandermonde matrix for the nodal distribution.
Definition: NodalUtil.cpp:101
virtual std::shared_ptr< NodalUtil > v_CreateUtil(Array< OneD, Array< OneD, NekDouble > > &xi)
Construct a NodalUtil object of the appropriate element type for a given set of points.
Definition: NodalUtil.h:192
Array< OneD, Array< OneD, NekDouble > > m_xi
Coordinates of the nodal points defining the basis.
Definition: NodalUtil.h:111
std::vector< Mode > m_ordering
Mapping from the indexing of the basis to a continuous ordering.
Definition: NodalUtil.h:280
virtual NekVector< NekDouble > v_OrthoBasis(const int mode)=0
Return the values of the orthogonal basis at the nodal points for a given mode.
virtual int v_NumModes()
Calculate the number of degrees of freedom for this element.
Definition: NodalUtil.h:253
Specialisation of the NodalUtil class to support nodal quad elements.
Definition: NodalUtil.h:311
int m_numPoints
Total number of nodal points.
Definition: NodalUtil.h:109
std::vector< std::pair< int, int > > m_ordering
Mapping from the indexing of the basis to a continuous ordering.
Definition: NodalUtil.h:325
virtual int v_NumModes()=0
Calculate the number of degrees of freedom 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...
virtual NekDouble v_ModeZeroIntegral()
Return the value of the integral of the zero-th mode for this element.
Definition: NodalUtil.h:248
virtual NekDouble v_ModeZeroIntegral()=0
Return the value of the integral of the zero-th mode for this element.
int m_dim
Dimension of the nodal element.
Definition: NodalUtil.h:105
Specialisation of the NodalUtil class to support nodal tetrahedral elements.
Definition: NodalUtil.h:214