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 ()=delete
 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 199 of file Basis.h.

Constructor & Destructor Documentation

◆ ~Basis()

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

Destructor.

Definition at line 206 of file Basis.h.

206{};

◆ Basis() [1/2]

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

Private constructor with BasisKey.

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

93 : m_basisKey(bkey), m_points(PointsManager()[bkey.GetPointsKey()]),
94 m_bdata(bkey.GetTotNumModes() * bkey.GetTotNumPoints()),
95 m_dbdata(bkey.GetTotNumModes() * bkey.GetTotNumPoints())
96{
97 m_InterpManager.RegisterGlobalCreator(
98 std::bind(&Basis::CalculateInterpMatrix, this, std::placeholders::_1));
99}
Array< OneD, NekDouble > m_dbdata
Derivative Basis definition.
Definition: Basis.h:326
PointsSharedPtr m_points
Set of points.
Definition: Basis.h:324
BasisKey m_basisKey
Basis specification.
Definition: Basis.h:323
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:328
Array< OneD, NekDouble > m_bdata
Basis definition.
Definition: Basis.h:325
PointsManagerT & PointsManager(void)

References CalculateInterpMatrix(), and m_InterpManager.

◆ Basis() [2/2]

Nektar::LibUtilities::Basis::Basis ( )
privatedelete

Private default constructor.

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 122 of file Foundations/Basis.cpp.

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

298 {
299 return m_basisKey.Collocation();
300 }
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 101 of file Foundations/Basis.cpp.

102{
103 std::shared_ptr<Basis> returnval(new Basis(bkey));
104 returnval->Initialize();
105
106 return returnval;
107}
Basis()=delete
Private default constructor.

References Basis().

◆ ExactIprodInt()

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

Determine if basis has exact integration for inner product.

Definition at line 291 of file Basis.h.

292 {
293 return m_basisKey.ExactIprodInt();
294 }
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 218 of file Foundations/Basis.cpp.

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

Referenced by Initialize().

◆ GetBaryWeights()

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

Definition at line 266 of file Basis.h.

267 {
268 return m_points->GetBaryWeights();
269 }

References m_points.

◆ GetBasisKey()

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

Returns the specification for the Basis.

Definition at line 315 of file Basis.h.

316 {
317 return m_basisKey;
318 }

References m_basisKey.

Referenced by Nektar::MultiRegions::ExpListHomogeneous2D::GenHomogeneous2DBlockMatrix().

◆ GetBasisType()

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

Return the type of expansion basis.

Definition at line 233 of file Basis.h.

234 {
235 return m_basisKey.GetBasisType();
236 }

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

Referenced by GenBasis().

◆ GetBdata()

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

Return basis definition array m_bdata.

Definition at line 303 of file Basis.h.

304 {
305 return m_bdata;
306 }

References m_bdata.

◆ GetD()

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

Definition at line 271 of file Basis.h.

273 {
274 return m_points->GetD(dir);
275 }

References m_points.

◆ GetDbdata()

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

Return basis definition array m_dbdata.

Definition at line 309 of file Basis.h.

310 {
311 return m_dbdata;
312 }

References m_dbdata.

◆ GetI() [1/2]

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

Definition at line 277 of file Basis.h.

279 {
280 return m_points->GetI(x);
281 }

References m_points.

◆ GetI() [2/2]

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

Definition at line 283 of file Basis.h.

284 {
285 ASSERTL0(bkey.GetPointsKey().GetPointsDim() == 1,
286 "Interpolation only to other 1d basis");
287 return m_InterpManager[bkey];
288 }

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

210 {
211 return m_basisKey.GetNumModes();
212 }

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

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

◆ GetNumPoints()

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

Return the number of points from the basis specification.

Definition at line 221 of file Basis.h.

222 {
223 return m_basisKey.GetNumPoints();
224 }
int GetNumPoints() const
Return points order at which basis is defined.
Definition: Basis.h:122

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

Referenced by GenBasis().

◆ GetPointsKey()

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

Return the points specification for the basis.

Definition at line 239 of file Basis.h.

240 {
241 return m_basisKey.GetPointsKey();
242 }

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

◆ GetPointsType()

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

Return the type of quadrature.

Definition at line 245 of file Basis.h.

246 {
247 return m_basisKey.GetPointsType();
248 }
PointsType GetPointsType() const
Return type of quadrature.
Definition: Basis.h:145

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

216 {
217 return m_basisKey.GetTotNumModes();
218 }
int GetTotNumModes() const
Definition: Basis.h:82

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

◆ GetTotNumPoints()

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

Return total number of points from the basis specification.

Definition at line 227 of file Basis.h.

228 {
230 }
int GetTotNumPoints() const
Definition: Basis.h:127

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

Referenced by Initialize().

◆ GetW()

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

Definition at line 255 of file Basis.h.

256 {
257 return m_points->GetW();
258 }

References m_points.

◆ GetZ()

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

Definition at line 250 of file Basis.h.

251 {
252 return m_points->GetZ();
253 }

References m_points.

◆ GetZW()

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

Definition at line 260 of file Basis.h.

262 {
263 m_points->GetZW(z, w);
264 }

References m_points, Nektar::UnitTests::w(), and Nektar::UnitTests::z().

◆ Initialize()

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

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

110{
111 ASSERTL0(GetNumModes() > 0,
112 "Cannot call Basis initialisation with zero or negative order");
113 ASSERTL0(GetTotNumPoints() > 0, "Cannot call Basis initialisation with "
114 "zero or negative numbers of points");
115
116 GenBasis();
117}
int GetTotNumPoints() const
Return total number of points from the basis specification.
Definition: Basis.h:227
void GenBasis()
Generate appropriate basis and their derivatives.

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

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:178

Definition at line 331 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 325 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 326 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 328 of file Basis.h.

Referenced by Basis(), and GetI().

◆ m_points

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

Set of points.

Definition at line 324 of file Basis.h.

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