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...
 
virtual 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 211 of file Basis.h.

Constructor & Destructor Documentation

◆ ~Basis()

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

Destructor.

Definition at line 218 of file Basis.h.

219  {
220  };

◆ Basis() [1/2]

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

Private constructor with BasisKey.

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

95  :
96  m_basisKey(bkey),
97  m_points(PointsManager()[bkey.GetPointsKey()]),
98  m_bdata(bkey.GetTotNumModes()*bkey.GetTotNumPoints()),
99  m_dbdata(bkey.GetTotNumModes()*bkey.GetTotNumPoints())
100  {
101  m_InterpManager.RegisterGlobalCreator(std::bind(&Basis::CalculateInterpMatrix,this,std::placeholders::_1));
102  }
Array< OneD, NekDouble > m_dbdata
Derivative Basis definition.
Definition: Basis.h:341
PointsSharedPtr m_points
Set of points.
Definition: Basis.h:339
BasisKey m_basisKey
Basis specification.
Definition: Basis.h:338
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:343
Array< OneD, NekDouble > m_bdata
Basis definition.
Definition: Basis.h:340
PointsManagerT & PointsManager(void)

References CalculateInterpMatrix(), and m_InterpManager.

◆ Basis() [2/2]

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

Private default constructor.

Definition at line 352 of file Basis.h.

353  {
355  "Default Constructor for Basis should not be called");
356  }
#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 124 of file Foundations/Basis.cpp.

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

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 312 of file Basis.h.

313  {
314  return m_basisKey.Collocation();
315  }
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 104 of file Foundations/Basis.cpp.

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

References Basis().

◆ ExactIprodInt()

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

Determine if basis has exact integration for inner product.

Definition at line 306 of file Basis.h.

307  {
308  return m_basisKey.ExactIprodInt();
309  }
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 217 of file Foundations/Basis.cpp.

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

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::eLegendre, Nektar::LibUtilities::eModified_A, Nektar::LibUtilities::eModified_B, Nektar::LibUtilities::eModified_C, Nektar::LibUtilities::eModifiedPyr_C, Nektar::LibUtilities::eMonomial, 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, CellMLToNektar.cellml_metadata::p, main::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 280 of file Basis.h.

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

References m_points.

◆ GetBasisKey()

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

Returns the specification for the Basis.

Definition at line 330 of file Basis.h.

331  {
332  return m_basisKey;
333  }

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 247 of file Basis.h.

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

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 318 of file Basis.h.

319  {
320  return m_bdata;
321  }

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 285 of file Basis.h.

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

References m_points.

◆ GetDbdata()

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

Return basis definition array m_dbdata.

Definition at line 324 of file Basis.h.

325  {
326  return m_dbdata;
327  }

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 291 of file Basis.h.

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

References m_points.

◆ GetI() [2/2]

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

Definition at line 297 of file Basis.h.

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

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 223 of file Basis.h.

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

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

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

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 253 of file Basis.h.

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

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 259 of file Basis.h.

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

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 229 of file Basis.h.

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

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

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

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 269 of file Basis.h.

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

References m_points.

Referenced by export_Basis().

◆ GetZ()

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

Definition at line 264 of file Basis.h.

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

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 274 of file Basis.h.

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

References m_points.

◆ Initialize()

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

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

114  {
115  ASSERTL0(GetNumModes()>0, "Cannot call Basis initialisation with zero or negative order");
116  ASSERTL0(GetTotNumPoints()>0, "Cannot call Basis initialisation with zero or negative numbers of points");
117 
118  GenBasis();
119  }
int GetTotNumPoints() const
Return total number of points from the basis specification.
Definition: Basis.h:241
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:176

Definition at line 346 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 340 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 341 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 343 of file Basis.h.

Referenced by Basis(), and GetI().

◆ m_points

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

Set of points.

Definition at line 339 of file Basis.h.

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