v0.15.0
Loading...
Searching...
No Matches
LegendrePolynomial.cpp
Go to the documentation of this file.
1/** \file LegendrePolynomial.cpp
2 * \brief Implementation of base for Legendre polynomials
3 */
4
5namespace MoFEM {
6
8LegendrePolynomialCtx::query_interface(boost::typeindex::type_index type_index,
9 UnknownInterface **iface) const {
10 *iface = const_cast<LegendrePolynomialCtx *>(this);
11 return 0;
12}
13
15LegendrePolynomial::query_interface(boost::typeindex::type_index type_index,
16 UnknownInterface **iface) const {
17 *iface = const_cast<LegendrePolynomial *>(this);
18 return 9;
19}
20
23 boost::shared_ptr<BaseFunctionCtx> ctx_ptr) {
24
26 auto ctx = ctx_ptr->getInterface<LegendrePolynomialCtx>();
27 ctx->baseFunPtr->resize(pts.size2(), ctx->P + 1, false);
28 ctx->baseDiffFunPtr->resize(pts.size2(), ctx->dIm * (ctx->P + 1), false);
29 double *l = NULL;
30 double *diff_l = NULL;
31 for (unsigned int gg = 0; gg < pts.size2(); gg++) {
32 if (ctx->baseFunPtr)
33 l = &((*ctx->baseFunPtr)(gg, 0));
34 if (ctx->baseDiffFunPtr)
35 diff_l = &((*ctx->baseDiffFunPtr)(gg, 0));
36 ierr = (ctx->basePolynomialsType0)(ctx->P, pts(0, gg), ctx->diffS, l,
37 diff_l, ctx->dIm);
39 }
41}
42
43/**
44\brief Calculate Legendre approximation basis
45
46\ingroup mofem_base_functions
47
48Lagrange polynomial is given by
49\f[
50L_0(s)=1;\quad L_1(s) = s
51\f]
52and following terms are generated inductively
53\f[
54L_{l+1}=\frac{2l+1}{l+1}sL_l(s)-\frac{l}{l+1}L_{l-1}(s)
55\f]
56
57Note that:
58\f[
59s\in[-1,1] \quad \textrm{and}\; s=s(\xi_0,\xi_1,\xi_2)
60\f]
61where \f$\xi_i\f$ are barycentric coordinates of element.
62
63\param p is approximation order
64\param s is position \f$s\in[-1,1]\f$
65\param diff_s derivatives of shape functions, i.e. \f$\frac{\partial s}{\partial
66\xi_i}\f$ \retval L approximation functions \retval diffL derivatives, i.e.
67\f$\frac{\partial L}{\partial \xi_i}\f$ \param dim dimension \return error code
68
69*/
70template <typename Scalar, typename DsScalar>
72 int p,
73 Scalar &s, // value of the coordinate
74 DsScalar *
75 diff_s, // gradient of s wrt physical coords; may be nullptr iff diffL==nullptr
76 Scalar *L, // size p+1
77 Scalar *diffL, // size dim*(p+1); may be nullptr
78 int dim) {
80
81#ifndef NDEBUG
82 if (dim < 1)
83 SETERRQ(PETSC_COMM_SELF, MOFEM_INVALID_DATA, "dim < 1");
84 if (dim > 3)
85 SETERRQ(PETSC_COMM_SELF, MOFEM_INVALID_DATA, "dim > 3");
86 if (p < 0)
87 SETERRQ(PETSC_COMM_SELF, MOFEM_INVALID_DATA, "p < 0");
88 if (diffL != nullptr && diff_s == nullptr)
89 SETERRQ(PETSC_COMM_SELF, MOFEM_INVALID_DATA,
90 "diff_s == NULL while diffL requested");
91#endif
92
93 // P0
94 L[0] = Scalar(1);
95 if (diffL) {
96 for (int d = 0; d < dim; ++d)
97 diffL[d * (p + 1) + 0] = Scalar(0);
98 }
99 if (p == 0)
101
102 // P1
103 L[1] = s;
104 if (diffL) {
105 for (int d = 0; d < dim; ++d)
106 diffL[d * (p + 1) + 1] = static_cast<Scalar>(diff_s[d]);
107 }
108 if (p == 1)
110
111 // Recurrence: P_{l+1} = A_l * s * P_l - B_l * P_{l-1}
112 for (int l = 1; l < p; ++l) {
113 const Scalar A = Scalar((2.0 * l + 1.0) / (l + 1.0));
114 const Scalar B = Scalar(double(l) / (l + 1.0));
115
116 L[l + 1] = A * s * L[l] - B * L[l - 1];
117
118 if (diffL) {
119 for (int d = 0; d < dim; ++d) {
120 const Scalar ds = static_cast<Scalar>(diff_s[d]);
121 // Chain rule: dP_{l+1} = A*( ds*P_l + s*dP_l ) - B*dP_{l-1}
122 diffL[d * (p + 1) + (l + 1)] =
123 A * (ds * L[l] + s * diffL[d * (p + 1) + l]) -
124 B * diffL[d * (p + 1) + (l - 1)];
125 }
126 }
127 }
128
130};
131
132PetscErrorCode Legendre_polynomials(int p, double s, double *diff_s, double *L,
133 double *diffL, int dim) {
134 return Legendre_polynomials_T(p, s, diff_s, L, diffL, dim);
135}
136
137PetscErrorCode Legendre_polynomials(int p, std::complex<double> s,
138 std::complex<double> *diff_s,
139 std::complex<double> *L,
140 std::complex<double> *diffL, int dim) {
141 return Legendre_polynomials_T<std::complex<double>, std::complex<double>>(
142 p, s, diff_s, L, diffL, dim);
143}
144
145} // namespace MoFEM
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERRG(n)
Check error code of MoFEM/MOAB/PETSc function.
@ MOFEM_INVALID_DATA
Definition definitions.h:36
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
MoFEMErrorCode Legendre_polynomials_T(int p, Scalar &s, DsScalar *diff_s, Scalar *L, Scalar *diffL, int dim)
Calculate Legendre approximation basis.
PetscErrorCode Legendre_polynomials(int p, double s, double *diff_s, double *L, double *diffL, int dim)
Calculate Legendre approximation basis.
FTensor::Index< 'l', 3 > l
static MoFEMErrorCodeGeneric< PetscErrorCode > ierr
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
constexpr AssemblyType A
Context class for Legendre basis function arguments.
MoFEMErrorCode query_interface(boost::typeindex::type_index type_index, UnknownInterface **iface) const
boost::shared_ptr< MatrixDouble > baseFunPtr
Pointer to base function matrix.
Class for calculating Legendre basis functions.
MoFEMErrorCode query_interface(boost::typeindex::type_index type_index, UnknownInterface **iface) const
MoFEMErrorCode getValue(MatrixDouble &pts, boost::shared_ptr< BaseFunctionCtx > ctx_ptr)
Evaluate Legendre basis functions at given points.
base class for all interface classes
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.