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

Represents a basis of a given type. More...

#include <Basis.h>

Public Member Functions

virtual ~Basis ()
 Destructor. More...
 
int GetNumModes () const
 Return order of basis from the basis specification. More...
 
int GetTotNumModes () const
 Return total number of modes from the basis specification. More...
 
int GetNumPoints () const
 Return the number of points from the basis specification. More...
 
int GetTotNumPoints () const
 Return total number of points from the basis specification. More...
 
BasisType GetBasisType () const
 Return the type of expansion basis. More...
 
PointsKey GetPointsKey () const
 Return the points specification for the basis. More...
 
PointsType GetPointsType () const
 Return the type of quadrature. More...
 
const Array< OneD, const NekDouble > & GetZ () const
 
const Array< OneD, const NekDouble > & GetW () const
 
void GetZW (Array< OneD, const NekDouble > &z, Array< OneD, const NekDouble > &w) const
 
const Array< OneD, const NekDouble > & GetBaryWeights () const
 
const std::shared_ptr< NekMatrix< NekDouble > > & GetD (Direction dir=xDir) const
 
const std::shared_ptr< NekMatrix< NekDouble > > GetI (const Array< OneD, const NekDouble > &x)
 
const std::shared_ptr< NekMatrix< NekDouble > > GetI (const BasisKey &bkey)
 
bool ExactIprodInt () const
 Determine if basis has exact integration for inner product. More...
 
bool Collocation () const
 Determine if basis has collocation properties. More...
 
const Array< OneD, const NekDouble > & GetBdata () const
 Return basis definition array m_bdata. More...
 
const Array< OneD, const NekDouble > & GetDbdata () const
 Return basis definition array m_dbdata. More...
 
const BasisKey GetBasisKey () const
 Returns the specification for the Basis. More...
 
void Initialize ()
 

Static Public Member Functions

static std::shared_ptr< BasisCreate (const BasisKey &bkey)
 Returns a new instance of a Basis with given BasisKey. More...
 

Protected Attributes

BasisKey m_basisKey
 Basis specification. More...
 
PointsSharedPtr m_points
 Set of points. More...
 
Array< OneD, NekDoublem_bdata
 Basis definition. More...
 
Array< OneD, NekDoublem_dbdata
 Derivative Basis definition. More...
 
NekManager< BasisKey, NekMatrix< NekDouble >, BasisKey::opLessm_InterpManager
 

Private Member Functions

 Basis (const BasisKey &bkey)
 Private constructor with BasisKey. More...
 
 Basis ()
 Private default constructor. More...
 
std::shared_ptr< NekMatrix< NekDouble > > CalculateInterpMatrix (const BasisKey &tbasis0)
 Calculate the interpolation Matrix for coefficient from one base (m_basisKey) to another (tbasis0) More...
 
void GenBasis ()
 Generate appropriate basis and their derivatives. More...
 

Static Private Attributes

static bool initBasisManager []
 

Detailed Description

Represents a basis of a given type.

Definition at line 212 of file Basis.h.

Constructor & Destructor Documentation

◆ ~Basis()

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

Destructor.

Definition at line 219 of file Basis.h.

219 {};

◆ Basis() [1/2]

Nektar::LibUtilities::Basis::Basis ( const BasisKey bkey)
private

Private constructor with BasisKey.

Definition at line 96 of file Foundations/Basis.cpp.

97  : m_basisKey(bkey), m_points(PointsManager()[bkey.GetPointsKey()]),
98  m_bdata(bkey.GetTotNumModes() * bkey.GetTotNumPoints()),
99  m_dbdata(bkey.GetTotNumModes() * bkey.GetTotNumPoints())
100 {
101  m_InterpManager.RegisterGlobalCreator(
102  std::bind(&Basis::CalculateInterpMatrix, this, std::placeholders::_1));
103 }
Array< OneD, NekDouble > m_dbdata
Derivative Basis definition.
Definition: Basis.h:339
PointsSharedPtr m_points
Set of points.
Definition: Basis.h:337
BasisKey m_basisKey
Basis specification.
Definition: Basis.h:336
std::shared_ptr< NekMatrix< NekDouble > > CalculateInterpMatrix(const BasisKey &tbasis0)
Calculate the interpolation Matrix for coefficient from one base (m_basisKey) to another (tbasis0)
NekManager< BasisKey, NekMatrix< NekDouble >, BasisKey::opLess > m_InterpManager
Definition: Basis.h:341
Array< OneD, NekDouble > m_bdata
Basis definition.
Definition: Basis.h:338
PointsManagerT & PointsManager(void)

References CalculateInterpMatrix(), and m_InterpManager.

◆ Basis() [2/2]

Nektar::LibUtilities::Basis::Basis ( )
inlineprivate

Private default constructor.

Definition at line 350 of file Basis.h.

351  {
353  "Default Constructor for Basis should not be called");
354  }
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
Definition: ErrorUtil.hpp:209
static const BasisKey NullBasisKey(eNoBasisType, 0, NullPointsKey)
Defines a null basis with no type or points.

References Nektar::ErrorUtil::efatal, and NEKERROR.

Referenced by Create().

Member Function Documentation

◆ CalculateInterpMatrix()

std::shared_ptr< NekMatrix< NekDouble > > Nektar::LibUtilities::Basis::CalculateInterpMatrix ( const BasisKey tbasis0)
private

Calculate the interpolation Matrix for coefficient from one base (m_basisKey) to another (tbasis0)

Definition at line 127 of file Foundations/Basis.cpp.

129 {
130  int dim = m_basisKey.GetNumModes();
131  const PointsKey pkey(dim, LibUtilities::eGaussLobattoLegendre);
132  BasisKey fbkey(m_basisKey.GetBasisType(), dim, pkey);
133  BasisKey tbkey(tbasis0.GetBasisType(), dim, pkey);
134 
135  // "Constructur" of the basis
136  BasisSharedPtr fbasis = BasisManager()[fbkey];
137  BasisSharedPtr tbasis = BasisManager()[tbkey];
138 
139  // Get B Matrices
140  Array<OneD, NekDouble> fB_data = fbasis->GetBdata();
141  Array<OneD, NekDouble> tB_data = tbasis->GetBdata();
142 
143  // Convert to a NekMatrix
144  NekMatrix<NekDouble> fB(dim, dim, fB_data);
145  NekMatrix<NekDouble> tB(dim, dim, tB_data);
146 
147  // Invert the "to" matrix: tu = tB^(-1)*fB fu = ftB fu
148  tB.Invert();
149 
150  // Compute transformation matrix
151  Array<OneD, NekDouble> zero1D(dim * dim, 0.0);
152  std::shared_ptr<NekMatrix<NekDouble>> ftB(
153  MemoryManager<NekMatrix<NekDouble>>::AllocateSharedPtr(dim, dim,
154  zero1D));
155  (*ftB) = tB * fB;
156 
157  return ftB;
158 }
BasisType GetBasisType() const
Return type of expansion basis.
Definition: Basis.h:141
int GetNumModes() const
Returns the order of the basis.
Definition: Basis.h:83
BasisManagerT & BasisManager(void)
std::shared_ptr< Basis > BasisSharedPtr
@ eGaussLobattoLegendre
1D Gauss-Lobatto-Legendre quadrature points
Definition: PointsType.h:53

References Nektar::LibUtilities::BasisManager(), Nektar::LibUtilities::eGaussLobattoLegendre, Nektar::LibUtilities::BasisKey::GetBasisType(), Nektar::LibUtilities::BasisKey::GetNumModes(), and m_basisKey.

Referenced by Basis().

◆ Collocation()

bool Nektar::LibUtilities::Basis::Collocation ( ) const
inline

Determine if basis has collocation properties.

Definition at line 310 of file Basis.h.

311  {
312  return m_basisKey.Collocation();
313  }
bool Collocation() const
Determine if basis has collocation properties.

References Nektar::LibUtilities::BasisKey::Collocation(), and m_basisKey.

◆ Create()

std::shared_ptr< Basis > Nektar::LibUtilities::Basis::Create ( const BasisKey bkey)
static

Returns a new instance of a Basis with given BasisKey.

Definition at line 105 of file Foundations/Basis.cpp.

106 {
107  std::shared_ptr<Basis> returnval(new Basis(bkey));
108  returnval->Initialize();
109 
110  return returnval;
111 }
Basis()
Private default constructor.
Definition: Basis.h:350

References Basis().

◆ ExactIprodInt()

bool Nektar::LibUtilities::Basis::ExactIprodInt ( void  ) const
inline

Determine if basis has exact integration for inner product.

Definition at line 304 of file Basis.h.

305  {
306  return m_basisKey.ExactIprodInt();
307  }
bool ExactIprodInt() const
Determine if basis has exact integration for inner product.

References Nektar::LibUtilities::BasisKey::ExactIprodInt(), and m_basisKey.

◆ GenBasis()

void Nektar::LibUtilities::Basis::GenBasis ( )
private

Generate appropriate basis and their derivatives.

The following expansions are generated depending on the enum type defined in m_basisKey.m_basistype:

NOTE: This definition does not follow the order in the Karniadakis & Sherwin book since this leads to a more compact hierarchical pattern for implementation purposes. The order of these modes dictates the ordering of the expansion coefficients.

In the following m_numModes = P

eModified_A:

m_bdata[i + j*m_numpoints] = \( \phi^a_i(z_j) = \left \{ \begin{array}{ll} \left ( \frac{1-z_j}{2}\right ) & i = 0 \\ \\ \left ( \frac{1+z_j}{2}\right ) & i = 1 \\ \\ \left ( \frac{1-z_j}{2}\right )\left ( \frac{1+z_j}{2}\right ) P^{1,1}_{i-2}(z_j) & 2\leq i < P\\ \end{array} \right . \)

eModified_B:

m_bdata[n(i,j) + k*m_numpoints] = \( \phi^b_{ij}(z_k) = \left \{ \begin{array}{lll} \phi^a_j(z_k) & i = 0, & 0\leq j < P \\ \\ \left ( \frac{1-z_k}{2}\right )^{i} & 1 \leq i < P,& j = 0 \\ \\ \left ( \frac{1-z_k}{2}\right )^{i} \left ( \frac{1+z_k}{2}\right ) P^{2i-1,1}_{j-1}(z_k) & 1 \leq i < P,\ & 1\leq j < P-i\ \\ \end{array} \right . , \)

where \( n(i,j) \) is a consecutive ordering of the triangular indices \( 0 \leq i, i+j < P \) where j runs fastest.

eModified_C:

m_bdata[n(i,j,k) + l*m_numpoints] = \( \phi^c_{ij,k}(z_l) = \phi^b_{i+j,k}(z_l) = \left \{ \begin{array}{llll} \phi^b_{j,k}(z_l) & i = 0, & 0\leq j < P & 0\leq k < P-j\\ \\ \left ( \frac{1-z_l}{2}\right )^{i+j} & 1\leq i < P,\ & 0\leq j < P-i,\ & k = 0 \\ \\ \left ( \frac{1-z_l}{2}\right )^{i+j} \left ( \frac{1+z_l}{2}\right ) P^{2i+2j-1,1}_{k-1}(z_k) & 1\leq i < P,& 0\leq j < P-i& 1\leq k < P-i-j \\ \\ \end{array} \right . , \)

where \( n(i,j,k) \) is a consecutive ordering of the triangular indices \( 0 \leq i, i+j, i+j+k < P \) where k runs fastest, then j and finally i.

Orthogonal basis A

\(\tilde \psi_p^a (\eta_1) = L_p(\eta_1) = P_p^{0,0}(\eta_1)\)

Orthogonal basis B

\(\tilde \psi_{pq}^b(\eta_2) = \left ( {1 - \eta_2} \over 2 \right)^p P_q^{2p+1,0}(\eta_2)\) \

Orthogonal basis C

\(\tilde \psi_{pqr}^c = \left ( {1 - \eta_3} \over 2 \right)^{p+q} P_r^{2p+2q+2, 0}(\eta_3)\) \ \

Orthogonal basis C for Pyramid expansion (which is richer than tets)

\(\tilde \psi_{pqr}^c = \left ( {1 - \eta_3} \over 2\right)^{pq} P_r^{2pq+2, 0}(\eta_3)\) \( \mbox{where }pq = max(p+q,0) \)

This orthogonal expansion has modes that are always in the Cartesian space, however the equivalent ModifiedPyr_C has vertex modes that do not lie in this space. If one chooses \(pq = max(p+q-1,0)\) then the expansion will space the same space as the vertices but the order of the expanion in 'r' is reduced by one.

1) Eta_z values are the changing the fastest, then r, q, and finally p. 2) r index increases by the stride of numPoints.

Definition at line 223 of file Foundations/Basis.cpp.

224 {
225  int i, p, q;
226  NekDouble scal;
227  Array<OneD, NekDouble> modeSharedArray;
228  NekDouble *mode;
229  Array<OneD, const NekDouble> z;
230  Array<OneD, const NekDouble> w;
231  const NekDouble *D;
232 
233  m_points->GetZW(z, w);
234 
235  D = &(m_points->GetD()->GetPtr())[0];
236  int numModes = GetNumModes();
237  int numPoints = GetNumPoints();
238 
239  switch (GetBasisType())
240  {
241 
242  /** \brief Orthogonal basis A
243 
244  \f$\tilde \psi_p^a (\eta_1) = L_p(\eta_1) = P_p^{0,0}(\eta_1)\f$
245 
246  */
247  case eOrtho_A:
248  case eLegendre:
249  mode = m_bdata.data();
250 
251  for (p = 0; p < numModes; ++p, mode += numPoints)
252  {
253  Polylib::jacobfd(numPoints, z.data(), mode, NULL, p, 0.0, 0.0);
254  // normalise
255  scal = sqrt(0.5 * (2.0 * p + 1.0));
256  for (i = 0; i < numPoints; ++i)
257  {
258  mode[i] *= scal;
259  }
260  }
261  // define derivative basis
262  Blas::Dgemm('n', 'n', numPoints, numModes, numPoints, 1.0, D,
263  numPoints, m_bdata.data(), numPoints, 0.0,
264  m_dbdata.data(), numPoints);
265  break;
266 
267  /** \brief Orthogonal basis B
268 
269  \f$\tilde \psi_{pq}^b(\eta_2) = \left ( {1 - \eta_2} \over 2 \right)^p
270  P_q^{2p+1,0}(\eta_2)\f$ \\
271 
272  */
273 
274  // This is tilde psi_pq in Spen's book, page 105
275  // The 3-dimensional array is laid out in memory such that
276  // 1) Eta_y values are the changing the fastest, then q and p.
277  // 2) q index increases by the stride of numPoints.
278  case eOrtho_B:
279  {
280  NekDouble *mode = m_bdata.data();
281 
282  for (int p = 0; p < numModes; ++p)
283  {
284  for (int q = 0; q < numModes - p; ++q, mode += numPoints)
285  {
286  Polylib::jacobfd(numPoints, z.data(), mode, NULL, q,
287  2 * p + 1.0, 0.0);
288  for (int j = 0; j < numPoints; ++j)
289  {
290  mode[j] *=
291  sqrt(p + q + 1.0) * pow(0.5 * (1.0 - z[j]), p);
292  }
293  }
294  }
295 
296  // define derivative basis
297  Blas::Dgemm('n', 'n', numPoints, numModes * (numModes + 1) / 2,
298  numPoints, 1.0, D, numPoints, m_bdata.data(), numPoints,
299  0.0, m_dbdata.data(), numPoints);
300  }
301  break;
302 
303  /** \brief Orthogonal basis C
304 
305  \f$\tilde \psi_{pqr}^c = \left ( {1 - \eta_3} \over 2 \right)^{p+q}
306  P_r^{2p+2q+2, 0}(\eta_3)\f$ \ \
307 
308  */
309 
310  // This is tilde psi_pqr in Spen's book, page 105
311  // The 4-dimensional array is laid out in memory such that
312  // 1) Eta_z values are the changing the fastest, then r, q, and finally
313  // p. 2) r index increases by the stride of numPoints.
314  case eOrtho_C:
315  {
316  int P = numModes - 1, Q = numModes - 1, R = numModes - 1;
317  NekDouble *mode = m_bdata.data();
318 
319  for (int p = 0; p <= P; ++p)
320  {
321  for (int q = 0; q <= Q - p; ++q)
322  {
323  for (int r = 0; r <= R - p - q; ++r, mode += numPoints)
324  {
325  Polylib::jacobfd(numPoints, z.data(), mode, NULL, r,
326  2 * p + 2 * q + 2.0, 0.0);
327  for (int k = 0; k < numPoints; ++k)
328  {
329  // Note factor of 0.5 is part of normalisation
330  mode[k] *= pow(0.5 * (1.0 - z[k]), p + q);
331 
332  // finish normalisation
333  mode[k] *= sqrt(r + p + q + 1.5);
334  }
335  }
336  }
337  }
338 
339  // Define derivative basis
340  Blas::Dgemm('n', 'n', numPoints,
341  numModes * (numModes + 1) * (numModes + 2) / 6,
342  numPoints, 1.0, D, numPoints, m_bdata.data(), numPoints,
343  0.0, m_dbdata.data(), numPoints);
344  }
345  break;
346 
347  /** \brief Orthogonal basis C for Pyramid expansion
348  (which is richer than tets)
349 
350  \f$\tilde \psi_{pqr}^c = \left ( {1 - \eta_3} \over
351  2\right)^{pq} P_r^{2pq+2, 0}(\eta_3)\f$ \f$ \mbox{where
352  }pq = max(p+q,0) \f$
353 
354  This orthogonal expansion has modes that are
355  always in the Cartesian space, however the
356  equivalent ModifiedPyr_C has vertex modes that do
357  not lie in this space. If one chooses \f$pq =
358  max(p+q-1,0)\f$ then the expansion will space the
359  same space as the vertices but the order of the
360  expanion in 'r' is reduced by one.
361 
362  1) Eta_z values are the changing the fastest, then
363  r, q, and finally p. 2) r index increases by the
364  stride of numPoints.
365  */
366  case eOrthoPyr_C:
367  {
368  int P = numModes - 1, Q = numModes - 1, R = numModes - 1;
369  NekDouble *mode = m_bdata.data();
370 
371  for (int p = 0; p <= P; ++p)
372  {
373  for (int q = 0; q <= Q; ++q)
374  {
375  for (int r = 0; r <= R - std::max(p, q);
376  ++r, mode += numPoints)
377  {
378  // this offset allows for orthogonal
379  // expansion to span linear FE space
380  // of modified basis but means that
381  // the cartesian polynomial space
382  // spanned by the expansion is one
383  // order lower.
384  // int pq = max(p + q -1,0);
385  int pq = std::max(p + q, 0);
386 
387  Polylib::jacobfd(numPoints, z.data(), mode, NULL, r,
388  2 * pq + 2.0, 0.0);
389  for (int k = 0; k < numPoints; ++k)
390  {
391  // Note factor of 0.5 is part of normalisation
392  mode[k] *= pow(0.5 * (1.0 - z[k]), pq);
393 
394  // finish normalisation
395  mode[k] *= sqrt(r + pq + 1.5);
396  }
397  }
398  }
399  }
400 
401  // Define derivative basis
402  Blas::Dgemm('n', 'n', numPoints,
403  numModes * (numModes + 1) * (numModes + 2) / 6,
404  numPoints, 1.0, D, numPoints, m_bdata.data(), numPoints,
405  0.0, m_dbdata.data(), numPoints);
406  }
407  break;
408 
409  case eModified_A:
410 
411  // Note the following packing deviates from the
412  // definition in the Book by Karniadakis in that we
413  // put the vertex degrees of freedom at the lower
414  // index range to follow a more hierarchic structure.
415 
416  for (i = 0; i < numPoints; ++i)
417  {
418  m_bdata[i] = 0.5 * (1 - z[i]);
419  m_bdata[numPoints + i] = 0.5 * (1 + z[i]);
420  }
421 
422  mode = m_bdata.data() + 2 * numPoints;
423 
424  for (p = 2; p < numModes; ++p, mode += numPoints)
425  {
426  Polylib::jacobfd(numPoints, z.data(), mode, NULL, p - 2, 1.0,
427  1.0);
428 
429  for (i = 0; i < numPoints; ++i)
430  {
431  mode[i] *= m_bdata[i] * m_bdata[numPoints + i];
432  }
433  }
434 
435  // define derivative basis
436  Blas::Dgemm('n', 'n', numPoints, numModes, numPoints, 1.0, D,
437  numPoints, m_bdata.data(), numPoints, 0.0,
438  m_dbdata.data(), numPoints);
439  break;
440 
441  case eModified_B:
442  {
443 
444  // Note the following packing deviates from the
445  // definition in the Book by Karniadakis in two
446  // ways. 1) We put the vertex degrees of freedom
447  // at the lower index range to follow a more
448  // hierarchic structure. 2) We do not duplicate
449  // the singular vertex definition so that only a
450  // triangular number (i.e. (modes)*(modes+1)/2) of
451  // modes are required consistent with the
452  // orthogonal basis.
453 
454  // In the current structure the q index runs
455  // faster than the p index so that the matrix has
456  // a more compact structure
457 
458  const NekDouble *one_m_z_pow, *one_p_z;
459 
460  // bdata should be of size order*(order+1)/2*zorder
461 
462  // first fow
463  for (i = 0; i < numPoints; ++i)
464  {
465  m_bdata[0 * numPoints + i] = 0.5 * (1 - z[i]);
466  m_bdata[1 * numPoints + i] = 0.5 * (1 + z[i]);
467  }
468 
469  mode = m_bdata.data() + 2 * numPoints;
470 
471  for (q = 2; q < numModes; ++q, mode += numPoints)
472  {
473  Polylib::jacobfd(numPoints, z.data(), mode, NULL, q - 2, 1.0,
474  1.0);
475 
476  for (i = 0; i < numPoints; ++i)
477  {
478  mode[i] *= m_bdata[i] * m_bdata[numPoints + i];
479  }
480  }
481 
482  // second row
483  for (i = 0; i < numPoints; ++i)
484  {
485  mode[i] = 0.5 * (1 - z[i]);
486  }
487 
488  mode += numPoints;
489 
490  for (q = 2; q < numModes; ++q, mode += numPoints)
491  {
492  Polylib::jacobfd(numPoints, z.data(), mode, NULL, q - 2, 1.0,
493  1.0);
494 
495  for (i = 0; i < numPoints; ++i)
496  {
497  mode[i] *= m_bdata[i] * m_bdata[numPoints + i];
498  }
499  }
500 
501  // third and higher rows
502  one_m_z_pow = m_bdata.data();
503  one_p_z = m_bdata.data() + numPoints;
504 
505  for (p = 2; p < numModes; ++p)
506  {
507  for (i = 0; i < numPoints; ++i)
508  {
509  mode[i] = m_bdata[i] * one_m_z_pow[i];
510  }
511 
512  one_m_z_pow = mode;
513  mode += numPoints;
514 
515  for (q = 1; q < numModes - p; ++q, mode += numPoints)
516  {
517  Polylib::jacobfd(numPoints, z.data(), mode, NULL, q - 1,
518  2 * p - 1, 1.0);
519 
520  for (i = 0; i < numPoints; ++i)
521  {
522  mode[i] *= one_m_z_pow[i] * one_p_z[i];
523  }
524  }
525  }
526 
527  Blas::Dgemm('n', 'n', numPoints, numModes * (numModes + 1) / 2,
528  numPoints, 1.0, D, numPoints, m_bdata.data(), numPoints,
529  0.0, m_dbdata.data(), numPoints);
530  }
531  break;
532 
533  case eModified_C:
534  {
535  // Note the following packing deviates from the
536  // definition in the Book by Karniadakis &
537  // Sherwin in two ways. 1) We put the vertex
538  // degrees of freedom at the lower index range to
539  // follow a more hierarchic structure. 2) We do
540  // not duplicate the singular vertex definition
541  // (or the duplicated face information in the book
542  // ) so that only a tetrahedral number
543  // (i.e. (modes)*(modes+1)*(modes+2)/6) of modes
544  // are required consistent with the orthogonal
545  // basis.
546 
547  // In the current structure the r index runs
548  // fastest rollowed by q and than the p index so
549  // that the matrix has a more compact structure
550 
551  // Note that eModified_C is a re-organisation/
552  // duplication of eModified_B so will get a
553  // temporary Modified_B expansion and copy the
554  // correct components.
555 
556  // Generate Modified_B basis;
557  BasisKey ModBKey(eModified_B, m_basisKey.GetNumModes(),
559  BasisSharedPtr ModB = BasisManager()[ModBKey];
560 
561  Array<OneD, const NekDouble> ModB_data = ModB->GetBdata();
562 
563  // Copy Modified_B basis into first
564  // (numModes*(numModes+1)/2)*numPoints entires of
565  // bdata. This fills in the complete (r,p) face.
566 
567  // Set up \phi^c_{p,q,r} = \phi^b_{p+q,r}
568 
569  int N;
570  int B_offset = 0;
571  int offset = 0;
572  for (p = 0; p < numModes; ++p)
573  {
574  N = numPoints * (numModes - p) * (numModes - p + 1) / 2;
575  Vmath::Vcopy(N, &ModB_data[0] + B_offset, 1,
576  &m_bdata[0] + offset, 1);
577  B_offset += numPoints * (numModes - p);
578  offset += N;
579  }
580 
581  // set up derivative of basis.
582  Blas::Dgemm('n', 'n', numPoints,
583  numModes * (numModes + 1) * (numModes + 2) / 6,
584  numPoints, 1.0, D, numPoints, m_bdata.data(), numPoints,
585  0.0, m_dbdata.data(), numPoints);
586  }
587  break;
588 
589  case eModifiedPyr_C:
590  {
591  // Note the following packing deviates from the
592  // definition in the Book by Karniadakis &
593  // Sherwin in two ways. 1) We put the vertex
594  // degrees of freedom at the lower index range to
595  // follow a more hierarchic structure. 2) We do
596  // not duplicate the singular vertex definition
597  // so that only a pyramidic number
598  // (i.e. (modes)*(modes+1)*(2*modes+1)/6) of modes
599  // are required consistent with the orthogonal
600  // basis.
601 
602  // In the current structure the r index runs
603  // fastest rollowed by q and than the p index so
604  // that the matrix has a more compact structure
605 
606  // Generate Modified_B basis;
607  BasisKey ModBKey(eModified_B, m_basisKey.GetNumModes(),
609  BasisSharedPtr ModB = BasisManager()[ModBKey];
610 
611  Array<OneD, const NekDouble> ModB_data = ModB->GetBdata();
612 
613  // Copy Modified_B basis into first
614  // (numModes*(numModes+1)/2)*numPoints entires of
615  // bdata.
616 
617  int N;
618  int B_offset = 0;
619  int offset = 0;
620 
621  // Vertex 0,3,4, edges 3,4,7, face 4
622  N = numPoints * (numModes) * (numModes + 1) / 2;
623  Vmath::Vcopy(N, &ModB_data[0], 1, &m_bdata[0], 1);
624  offset += N;
625 
626  B_offset += numPoints * (numModes);
627  // Vertex 1 edges 5
628  N = numPoints * (numModes - 1);
629  Vmath::Vcopy(N, &ModB_data[0] + B_offset, 1, &m_bdata[0] + offset,
630  1);
631  offset += N;
632 
633  // Vertex 2 edges 1,6, face 2
634  N = numPoints * (numModes - 1) * (numModes) / 2;
635  Vmath::Vcopy(N, &ModB_data[0] + B_offset, 1, &m_bdata[0] + offset,
636  1);
637  offset += N;
638 
639  B_offset += numPoints * (numModes - 1);
640 
641  NekDouble *one_m_z_pow, *one_p_z;
642  NekDouble *mode;
643 
644  mode = m_bdata.data() + offset;
645 
646  for (p = 2; p < numModes; ++p)
647  {
648  // edges 0 2, faces 1 3
649  N = numPoints * (numModes - p);
650  Vmath::Vcopy(N, &ModB_data[0] + B_offset, 1, mode, 1);
651  mode += N;
652  Vmath::Vcopy(N, &ModB_data[0] + B_offset, 1, mode, 1);
653  mode += N;
654  B_offset += N;
655 
656  one_p_z = m_bdata.data() + numPoints;
657 
658  for (q = 2; q < numModes; ++q)
659  {
660  // face 0
661  for (i = 0; i < numPoints; ++i)
662  {
663  // [(1-z)/2]^{p+q-2} Note in book it
664  // seems to suggest p+q-1 but that
665  // does not seem to give complete
666  // polynomial space for pyramids
667  mode[i] = pow(m_bdata[i], p + q - 2);
668  }
669 
670  one_m_z_pow = mode;
671  mode += numPoints;
672 
673  // interior
674  for (int r = 1; r < numModes - std::max(p, q); ++r)
675  {
676  Polylib::jacobfd(numPoints, z.data(), mode, NULL, r - 1,
677  2 * p + 2 * q - 3, 1.0);
678 
679  for (i = 0; i < numPoints; ++i)
680  {
681  mode[i] *= one_m_z_pow[i] * one_p_z[i];
682  }
683  mode += numPoints;
684  }
685  }
686  }
687 
688  // set up derivative of basis.
689  Blas::Dgemm('n', 'n', numPoints,
690  numModes * (numModes + 1) * (2 * numModes + 1) / 6,
691  numPoints, 1.0, D, numPoints, m_bdata.data(), numPoints,
692  0.0, m_dbdata.data(), numPoints);
693  }
694  break;
695 
696  case eGLL_Lagrange:
697  {
698  mode = m_bdata.data();
699  std::shared_ptr<Points<NekDouble>> m_points =
700  PointsManager()[PointsKey(numModes, eGaussLobattoLegendre)];
701  const Array<OneD, const NekDouble> &zp(m_points->GetZ());
702 
703  for (p = 0; p < numModes; ++p, mode += numPoints)
704  {
705  for (q = 0; q < numPoints; ++q)
706  {
707  mode[q] =
708  Polylib::hglj(p, z[q], zp.data(), numModes, 0.0, 0.0);
709  }
710  }
711 
712  // define derivative basis
713  Blas::Dgemm('n', 'n', numPoints, numModes, numPoints, 1.0, D,
714  numPoints, m_bdata.data(), numPoints, 0.0,
715  m_dbdata.data(), numPoints);
716 
717  } // end scope
718  break;
719  case eGauss_Lagrange:
720  {
721  mode = m_bdata.data();
722  std::shared_ptr<Points<NekDouble>> m_points =
723  PointsManager()[PointsKey(numModes, eGaussGaussLegendre)];
724  const Array<OneD, const NekDouble> &zp(m_points->GetZ());
725 
726  for (p = 0; p < numModes; ++p, mode += numPoints)
727  {
728  for (q = 0; q < numPoints; ++q)
729  {
730  mode[q] =
731  Polylib::hgj(p, z[q], zp.data(), numModes, 0.0, 0.0);
732  }
733  }
734 
735  // define derivative basis
736  Blas::Dgemm('n', 'n', numPoints, numModes, numPoints, 1.0, D,
737  numPoints, m_bdata.data(), numPoints, 0.0,
738  m_dbdata.data(), numPoints);
739 
740  } // end scope
741  break;
742  case eFourier:
743 
744  ASSERTL0(numModes % 2 == 0,
745  "Fourier modes should be a factor of 2");
746 
747  for (i = 0; i < numPoints; ++i)
748  {
749  m_bdata[i] = 1.0;
750  m_bdata[numPoints + i] = 0.0;
751 
752  m_dbdata[i] = m_dbdata[numPoints + i] = 0.0;
753  }
754 
755  for (p = 1; p < numModes / 2; ++p)
756  {
757  for (i = 0; i < numPoints; ++i)
758  {
759  m_bdata[2 * p * numPoints + i] = cos(p * M_PI * (z[i] + 1));
760  m_bdata[(2 * p + 1) * numPoints + i] =
761  -sin(p * M_PI * (z[i] + 1));
762 
763  m_dbdata[2 * p * numPoints + i] =
764  -p * M_PI * sin(p * M_PI * (z[i] + 1));
765  m_dbdata[(2 * p + 1) * numPoints + i] =
766  -p * M_PI * cos(p * M_PI * (z[i] + 1));
767  }
768  }
769 
770  break;
771 
772  // Fourier Single Mode (1st mode)
773  case eFourierSingleMode:
774 
775  for (i = 0; i < numPoints; ++i)
776  {
777  m_bdata[i] = cos(M_PI * (z[i] + 1));
778  m_bdata[numPoints + i] = -sin(M_PI * (z[i] + 1));
779 
780  m_dbdata[i] = -M_PI * sin(M_PI * (z[i] + 1));
781  m_dbdata[numPoints + i] = -M_PI * cos(M_PI * (z[i] + 1));
782  }
783 
784  for (p = 1; p < numModes / 2; ++p)
785  {
786  for (i = 0; i < numPoints; ++i)
787  {
788  m_bdata[2 * p * numPoints + i] = 0.;
789  m_bdata[(2 * p + 1) * numPoints + i] = 0.;
790 
791  m_dbdata[2 * p * numPoints + i] = 0.;
792  m_dbdata[(2 * p + 1) * numPoints + i] = 0.;
793  }
794  }
795  break;
796 
797  // Fourier Real Half Mode
798  case eFourierHalfModeRe:
799  m_bdata[0] = cos(M_PI * z[0]);
800  m_dbdata[0] = -M_PI * sin(M_PI * z[0]);
801  break;
802 
803  // Fourier Imaginary Half Mode
804  case eFourierHalfModeIm:
805  m_bdata[0] = -sin(M_PI * z[0]);
806  m_dbdata[0] = -M_PI * cos(M_PI * z[0]);
807  break;
808 
809  case eChebyshev:
810  {
811  mode = m_bdata.data();
812 
813  for (p = 0, scal = 1; p < numModes; ++p, mode += numPoints)
814  {
815  Polylib::jacobfd(numPoints, z.data(), mode, NULL, p, -0.5,
816  -0.5);
817 
818  for (i = 0; i < numPoints; ++i)
819  {
820  mode[i] *= scal;
821  }
822 
823  scal *= 4 * (p + 1) * (p + 1) / (2 * p + 2) / (2 * p + 1);
824  }
825 
826  // Define derivative basis
827  Blas::Dgemm('n', 'n', numPoints, numModes, numPoints, 1.0, D,
828  numPoints, m_bdata.data(), numPoints, 0.0,
829  m_dbdata.data(), numPoints);
830  }
831  break;
832 
833  case eMonomial:
834  {
835  int P = numModes - 1;
836  NekDouble *mode = m_bdata.data();
837 
838  for (int p = 0; p <= P; ++p, mode += numPoints)
839  {
840  for (int i = 0; i < numPoints; ++i)
841  {
842  mode[i] = pow(z[i], p);
843  }
844  }
845 
846  // define derivative basis
847  Blas::Dgemm('n', 'n', numPoints, numModes, numPoints, 1.0, D,
848  numPoints, m_bdata.data(), numPoints, 0.0,
849  m_dbdata.data(), numPoints);
850  } // end scope
851  break;
852  default:
853  NEKERROR(ErrorUtil::efatal, "Basis Type not known or "
854  "not implemented at this time.");
855  }
856 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
int GetNumModes() const
Return order of basis from the basis specification.
Definition: Basis.h:222
BasisType GetBasisType() const
Return the type of expansion basis.
Definition: Basis.h:246
int GetNumPoints() const
Return the number of points from the basis specification.
Definition: Basis.h:234
PointsKey GetPointsKey() const
Return distribution of points.
Definition: Basis.h:147
static void Dgemm(const char &transa, const char &transb, const int &m, const int &n, const int &k, const double &alpha, const double *a, const int &lda, const double *b, const int &ldb, const double &beta, double *c, const int &ldc)
BLAS level 3: Matrix-matrix multiply C = A x B where op(A)[m x k], op(B)[k x n], C[m x n] DGEMM perfo...
Definition: Blas.hpp:368
@ eGaussGaussLegendre
1D Gauss-Gauss-Legendre quadrature points
Definition: PointsType.h:48
@ eModified_B
Principle Modified Functions .
Definition: BasisType.h:51
@ eGauss_Lagrange
Lagrange Polynomials using the Gauss points.
Definition: BasisType.h:59
@ eOrtho_A
Principle Orthogonal Functions .
Definition: BasisType.h:44
@ eModified_C
Principle Modified Functions .
Definition: BasisType.h:52
@ eGLL_Lagrange
Lagrange for SEM basis .
Definition: BasisType.h:58
@ eFourierSingleMode
Fourier ModifiedExpansion with just the first mode .
Definition: BasisType.h:66
@ eChebyshev
Chebyshev Polynomials.
Definition: BasisType.h:63
@ eOrtho_C
Principle Orthogonal Functions .
Definition: BasisType.h:48
@ eModifiedPyr_C
Principle Modified Functions.
Definition: BasisType.h:55
@ eOrtho_B
Principle Orthogonal Functions .
Definition: BasisType.h:46
@ eModified_A
Principle Modified Functions .
Definition: BasisType.h:50
@ eFourierHalfModeIm
Fourier Modified expansions with just the imaginary part of the first mode .
Definition: BasisType.h:70
@ eFourierHalfModeRe
Fourier Modified expansions with just the real part of the first mode .
Definition: BasisType.h:68
@ eOrthoPyr_C
Principle Orthogonal Functions .
Definition: BasisType.h:53
@ eFourier
Fourier Expansion .
Definition: BasisType.h:57
double NekDouble
double hgj(const int i, const double z, const double *zgj, const int np, const double alpha, const double beta)
Compute the value of the i th Lagrangian interpolant through the np Gauss-Jacobi points zgj at the ar...
Definition: Polylib.cpp:858
double hglj(const int i, const double z, const double *zglj, const int np, const double alpha, const double beta)
Compute the value of the i th Lagrangian interpolant through the np Gauss-Lobatto-Jacobi points zgrj ...
Definition: Polylib.cpp:964
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
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1255
scalarT< T > sqrt(scalarT< T > in)
Definition: scalar.hpp:294

References ASSERTL0, Nektar::LibUtilities::BasisManager(), Blas::Dgemm(), Nektar::LibUtilities::eChebyshev, Nektar::ErrorUtil::efatal, Nektar::LibUtilities::eFourier, Nektar::LibUtilities::eFourierHalfModeIm, Nektar::LibUtilities::eFourierHalfModeRe, Nektar::LibUtilities::eFourierSingleMode, Nektar::LibUtilities::eGauss_Lagrange, Nektar::LibUtilities::eGaussGaussLegendre, Nektar::LibUtilities::eGaussLobattoLegendre, Nektar::LibUtilities::eGLL_Lagrange, Nektar::LibUtilities::eModified_A, Nektar::LibUtilities::eModified_B, Nektar::LibUtilities::eModified_C, Nektar::LibUtilities::eModifiedPyr_C, Nektar::LibUtilities::eOrtho_A, Nektar::LibUtilities::eOrtho_B, Nektar::LibUtilities::eOrtho_C, Nektar::LibUtilities::eOrthoPyr_C, GetBasisType(), Nektar::LibUtilities::BasisKey::GetNumModes(), GetNumModes(), GetNumPoints(), Nektar::LibUtilities::BasisKey::GetPointsKey(), Polylib::hgj(), Polylib::hglj(), Polylib::jacobfd(), m_basisKey, m_bdata, m_dbdata, m_points, NEKERROR, Nektar::LibUtilities::P, CellMLToNektar.cellml_metadata::p, Nektar::LibUtilities::PointsManager(), tinysimd::sqrt(), and Vmath::Vcopy().

Referenced by Initialize().

◆ GetBaryWeights()

const Array<OneD, const NekDouble>& Nektar::LibUtilities::Basis::GetBaryWeights ( ) const
inline

Definition at line 279 of file Basis.h.

280  {
281  return m_points->GetBaryWeights();
282  }

References m_points.

◆ GetBasisKey()

const BasisKey Nektar::LibUtilities::Basis::GetBasisKey ( ) const
inline

Returns the specification for the Basis.

Definition at line 328 of file Basis.h.

329  {
330  return m_basisKey;
331  }

References m_basisKey.

Referenced by export_Basis(), and Nektar::MultiRegions::ExpListHomogeneous2D::GenHomogeneous2DBlockMatrix().

◆ GetBasisType()

BasisType Nektar::LibUtilities::Basis::GetBasisType ( ) const
inline

Return the type of expansion basis.

Definition at line 246 of file Basis.h.

247  {
248  return m_basisKey.GetBasisType();
249  }

References Nektar::LibUtilities::BasisKey::GetBasisType(), and m_basisKey.

Referenced by export_Basis(), and GenBasis().

◆ GetBdata()

const Array<OneD, const NekDouble>& Nektar::LibUtilities::Basis::GetBdata ( ) const
inline

Return basis definition array m_bdata.

Definition at line 316 of file Basis.h.

317  {
318  return m_bdata;
319  }

References m_bdata.

Referenced by Nektar::LocalRegions::Expansion1D::AddHDGHelmholtzTraceTerms(), Nektar::LocalRegions::Expansion1D::AddNormTraceInt(), and export_Basis().

◆ GetD()

const std::shared_ptr<NekMatrix<NekDouble> >& Nektar::LibUtilities::Basis::GetD ( Direction  dir = xDir) const
inline

Definition at line 284 of file Basis.h.

286  {
287  return m_points->GetD(dir);
288  }

References m_points.

◆ GetDbdata()

const Array<OneD, const NekDouble>& Nektar::LibUtilities::Basis::GetDbdata ( ) const
inline

Return basis definition array m_dbdata.

Definition at line 322 of file Basis.h.

323  {
324  return m_dbdata;
325  }

References m_dbdata.

Referenced by export_Basis().

◆ GetI() [1/2]

const std::shared_ptr<NekMatrix<NekDouble> > Nektar::LibUtilities::Basis::GetI ( const Array< OneD, const NekDouble > &  x)
inline

Definition at line 290 of file Basis.h.

292  {
293  return m_points->GetI(x);
294  }

References m_points.

◆ GetI() [2/2]

const std::shared_ptr<NekMatrix<NekDouble> > Nektar::LibUtilities::Basis::GetI ( const BasisKey bkey)
inline

Definition at line 296 of file Basis.h.

297  {
298  ASSERTL0(bkey.GetPointsKey().GetPointsDim() == 1,
299  "Interpolation only to other 1d basis");
300  return m_InterpManager[bkey];
301  }

References ASSERTL0, Nektar::LibUtilities::PointsKey::GetPointsDim(), Nektar::LibUtilities::BasisKey::GetPointsKey(), and m_InterpManager.

◆ GetNumModes()

int Nektar::LibUtilities::Basis::GetNumModes ( ) const
inline

Return order of basis from the basis specification.

Definition at line 222 of file Basis.h.

223  {
224  return m_basisKey.GetNumModes();
225  }

References Nektar::LibUtilities::BasisKey::GetNumModes(), and m_basisKey.

Referenced by export_Basis(), GenBasis(), Initialize(), and main().

◆ GetNumPoints()

int Nektar::LibUtilities::Basis::GetNumPoints ( ) const
inline

Return the number of points from the basis specification.

Definition at line 234 of file Basis.h.

235  {
236  return m_basisKey.GetNumPoints();
237  }
int GetNumPoints() const
Return points order at which basis is defined.
Definition: Basis.h:130

References Nektar::LibUtilities::BasisKey::GetNumPoints(), and m_basisKey.

Referenced by export_Basis(), and GenBasis().

◆ GetPointsKey()

PointsKey Nektar::LibUtilities::Basis::GetPointsKey ( ) const
inline

Return the points specification for the basis.

Definition at line 252 of file Basis.h.

253  {
254  return m_basisKey.GetPointsKey();
255  }

References Nektar::LibUtilities::BasisKey::GetPointsKey(), and m_basisKey.

Referenced by export_Basis().

◆ GetPointsType()

PointsType Nektar::LibUtilities::Basis::GetPointsType ( ) const
inline

Return the type of quadrature.

Definition at line 258 of file Basis.h.

259  {
260  return m_basisKey.GetPointsType();
261  }
PointsType GetPointsType() const
Return type of quadrature.
Definition: Basis.h:153

References Nektar::LibUtilities::BasisKey::GetPointsType(), and m_basisKey.

◆ GetTotNumModes()

int Nektar::LibUtilities::Basis::GetTotNumModes ( ) const
inline

Return total number of modes from the basis specification.

Definition at line 228 of file Basis.h.

229  {
230  return m_basisKey.GetTotNumModes();
231  }
int GetTotNumModes() const
Definition: Basis.h:89

References Nektar::LibUtilities::BasisKey::GetTotNumModes(), and m_basisKey.

Referenced by export_Basis().

◆ GetTotNumPoints()

int Nektar::LibUtilities::Basis::GetTotNumPoints ( ) const
inline

Return total number of points from the basis specification.

Definition at line 240 of file Basis.h.

241  {
242  return m_basisKey.GetTotNumPoints();
243  }
int GetTotNumPoints() const
Definition: Basis.h:135

References Nektar::LibUtilities::BasisKey::GetTotNumPoints(), and m_basisKey.

Referenced by export_Basis(), and Initialize().

◆ GetW()

const Array<OneD, const NekDouble>& Nektar::LibUtilities::Basis::GetW ( ) const
inline

Definition at line 268 of file Basis.h.

269  {
270  return m_points->GetW();
271  }

References m_points.

Referenced by export_Basis().

◆ GetZ()

const Array<OneD, const NekDouble>& Nektar::LibUtilities::Basis::GetZ ( ) const
inline

Definition at line 263 of file Basis.h.

264  {
265  return m_points->GetZ();
266  }

References m_points.

Referenced by export_Basis().

◆ GetZW()

void Nektar::LibUtilities::Basis::GetZW ( Array< OneD, const NekDouble > &  z,
Array< OneD, const NekDouble > &  w 
) const
inline

Definition at line 273 of file Basis.h.

275  {
276  m_points->GetZW(z, w);
277  }

References m_points.

◆ Initialize()

void Nektar::LibUtilities::Basis::Initialize ( )

Definition at line 113 of file Foundations/Basis.cpp.

115 {
116  ASSERTL0(GetNumModes() > 0,
117  "Cannot call Basis initialisation with zero or negative order");
118  ASSERTL0(GetTotNumPoints() > 0, "Cannot call Basis initialisation with "
119  "zero or negative numbers of points");
120 
121  GenBasis();
122 }
int GetTotNumPoints() const
Return total number of points from the basis specification.
Definition: Basis.h:240
void GenBasis()
Generate appropriate basis and their derivatives.

References ASSERTL0, GenBasis(), GetNumModes(), and GetTotNumPoints().

Referenced by export_Basis().

Member Data Documentation

◆ initBasisManager

bool Nektar::LibUtilities::Basis::initBasisManager
staticprivate
Initial value:
= {
static std::shared_ptr< Basis > Create(const BasisKey &bkey)
Returns a new instance of a Basis with given BasisKey.
bool RegisterGlobalCreator(const CreateFuncType &createFunc)
Register the Global Create Function. The return value is just to facilitate calling statically.
Definition: NekManager.hpp:179

Definition at line 344 of file Basis.h.

◆ m_basisKey

BasisKey Nektar::LibUtilities::Basis::m_basisKey
protected

◆ m_bdata

Array<OneD, NekDouble> Nektar::LibUtilities::Basis::m_bdata
protected

Basis definition.

Definition at line 338 of file Basis.h.

Referenced by GenBasis(), and GetBdata().

◆ m_dbdata

Array<OneD, NekDouble> Nektar::LibUtilities::Basis::m_dbdata
protected

Derivative Basis definition.

Definition at line 339 of file Basis.h.

Referenced by GenBasis(), and GetDbdata().

◆ m_InterpManager

NekManager<BasisKey, NekMatrix<NekDouble>, BasisKey::opLess> Nektar::LibUtilities::Basis::m_InterpManager
protected

Definition at line 341 of file Basis.h.

Referenced by Basis(), and GetI().

◆ m_points

PointsSharedPtr Nektar::LibUtilities::Basis::m_points
protected

Set of points.

Definition at line 337 of file Basis.h.

Referenced by GenBasis(), GetBaryWeights(), GetD(), GetI(), GetW(), GetZ(), and GetZW().