4#ifndef DUNE_LOCALFUNCTIONS_SERENDIPITYLOCALBASIS_HH
5#define DUNE_LOCALFUNCTIONS_SERENDIPITYLOCALBASIS_HH
7#include <dune/common/fvector.hh>
8#include <dune/common/fmatrix.hh>
9#include <dune/common/power.hh>
11#include <dune/geometry/type.hh>
13#include <dune/localfunctions/common/localbasis.hh>
14#include <dune/localfunctions/common/localfiniteelementtraits.hh>
29 template<
class D,
class R,
int k,
int d>
32 typedef typename Dune::FieldVector<int,d> DuneVector;
36 static R p (
int i,
int deg, D x)
39 for (
int j=0; j<=deg; j++)
40 if (j!=i) result *= (deg*x-j)/(i-j);
45 static R dp (
int i,
int deg, D x)
49 for (
int j=0; j<=deg; j++)
52 R prod( (deg*1.0)/(i-j) );
53 for (
int l=0; l<=deg; l++)
55 prod *= (deg*x-l)/(i-l);
61 static void multiindex (DuneVector& alpha)
64 for (
int j=0; j<d; j++){
65 i+=alpha[j]*pow(k+1,j);
68 for (
int j=0; j<d; j++)
74 for (
unsigned int j=0; j<d; j++){
75 if(alpha[j] > 0 && alpha[j] < k){ sum++; }
82 bool isEdge(DuneVector& alpha)
const{
83 for(
int i = 0; i < d; i++){
84 if(alpha[i]>0 && alpha[i] < k)
90 double edgeVal(
int alpha,
const double& in,
int der)
const{
92 if(alpha > 0 && alpha < k){
96 return dp(alpha,k,in);
100 return p(alpha/k,k-1,in);
102 return dp(alpha/k,k-1,in);
106 double nodeVal(
int alpha,
const double& in,
int der)
const{
108 if(k == 1 && der == 0)
109 return p(alpha,k,in);
110 if(k == 1 && der > 0)
111 return dp(alpha,k, in);
113 return p(alpha/k,k-1,in);
115 return dp(alpha/k,k-1,in);
119 typedef LocalBasisTraits<D,d,Dune::FieldVector<D,d>,R,1,Dune::FieldVector<R,1>,Dune::FieldMatrix<R,1,d>, 1> Traits;
128 return 2*(k+1)+2*(k-1);
131 return 4*(k+1)+8*(k-1);
137 std::vector<typename Traits::RangeType>& out)
const
141 for (
size_t i=0; i<
size(); i++)
144 if(i>0){ multiindex(alpha); }
147 for(
int j = 0; j < d; j++){
149 out[i] *= edgeVal(alpha[j], in[j], 0);
151 out[i] *= nodeVal(alpha[j], in[j], 0);
157 out[0] -= 0.5*(out[1]+out[3]);
158 out[2] -= 0.5*(out[1]+out[4]);
159 out[5] -= 0.5*(out[3]+out[6]);
160 out[7] -= 0.5*(out[4]+out[6]);
163 out[0] -= 0.5*(out[1] +out[3] +out[8]);
164 out[2] -= 0.5*(out[1] +out[4] +out[9]);
165 out[5] -= 0.5*(out[3] +out[6] +out[10]);
166 out[7] -= 0.5*(out[4] +out[6] +out[11]);
167 out[12] -= 0.5*(out[8] +out[13]+out[15]);
168 out[14] -= 0.5*(out[9] +out[13]+out[16]);
169 out[17] -= 0.5*(out[10]+out[15]+out[18]);
170 out[19] -= 0.5*(out[11]+out[16]+out[18]);
215 std::vector<typename Traits::JacobianType>& out)
const
221 for (
size_t i=0; i<
size(); i++)
224 if(i>0){ multiindex(alpha); }
228 for (
int j=0; j<d; j++)
233 out[i][0][j] *= edgeVal(alpha[j],in[j], 1);
235 out[i][0][j] *= nodeVal(alpha[j],in[j], 1);
237 for (
int l=0; l<d; l++){
240 out[i][0][j] *= edgeVal(alpha[l],in[l],0);
242 out[i][0][j] *= nodeVal(alpha[l],in[l],0);
249 for(
int j = 0; j < d; j++){
250 out[0][0][j] -= 0.5*(out[1][0][j]+out[3][0][j]);
251 out[2][0][j] -= 0.5*(out[1][0][j]+out[4][0][j]);
252 out[5][0][j] -= 0.5*(out[3][0][j]+out[6][0][j]);
253 out[7][0][j] -= 0.5*(out[4][0][j]+out[6][0][j]);
257 for(
int j = 0; j < d; j++){
258 out[0][0][j] -= 0.5*(out[1][0][j] +out[3][0][j] +out[8][0][j]);
259 out[2][0][j] -= 0.5*(out[1][0][j] +out[4][0][j] +out[9][0][j]);
260 out[5][0][j] -= 0.5*(out[3][0][j] +out[6][0][j] +out[10][0][j]);
261 out[7][0][j] -= 0.5*(out[4][0][j] +out[6][0][j] +out[11][0][j]);
262 out[12][0][j] -= 0.5*(out[8][0][j] +out[13][0][j]+out[15][0][j]);
263 out[14][0][j] -= 0.5*(out[9][0][j] +out[13][0][j]+out[16][0][j]);
264 out[17][0][j] -= 0.5*(out[10][0][j]+out[15][0][j]+out[18][0][j]);
265 out[19][0][j] -= 0.5*(out[11][0][j]+out[16][0][j]+out[18][0][j]);
276 template<
int diffOrder>
278 const std::array<int,1>& direction,
279 const typename Traits::DomainType& in,
280 std::vector<typename Traits::RangeType>& out)
const
282 static_assert(diffOrder == 1,
"We only can compute first derivatives");
287 for (
size_t i=0; i<
size(); i++)
290 if(i>0){ multiindex(alpha);}
293 std::size_t j = direction[0];
299 out[i][0] *= edgeVal(alpha[j],in[j],1);
301 out[i][0] *= nodeVal(alpha[j],in[j],1);
304 for (std::size_t l=0; l<d; l++){
307 out[i][0] *= edgeVal(alpha[l],in[l],0);
309 out[i][0] *= nodeVal(alpha[l],in[l],0);
315 out[0][0] -= 0.5*(out[1][0]+out[3][0]);
316 out[2][0] -= 0.5*(out[1][0]+out[4][0]);
317 out[5][0] -= 0.5*(out[3][0]+out[6][0]);
318 out[7][0] -= 0.5*(out[4][0]+out[6][0]);
321 out[0][0] -= 0.5*(out[1][0] +out[3][0] +out[8][0]);
322 out[2][0] -= 0.5*(out[1][0] +out[4][0] +out[9][0]);
323 out[5][0] -= 0.5*(out[3][0] +out[6][0] +out[10][0]);
324 out[7][0] -= 0.5*(out[4][0] +out[6][0] +out[11][0]);
325 out[12][0] -= 0.5*(out[8][0] +out[13][0]+out[15][0]);
326 out[14][0] -= 0.5*(out[9][0] +out[13][0]+out[16][0]);
327 out[17][0] -= 0.5*(out[10][0]+out[15][0]+out[18][0]);
328 out[19][0] -= 0.5*(out[11][0]+out[16][0]+out[18][0]);
Serendipity basis functions of order k on the reference cube.
Definition: serendipitylocalbasis.hh:31
unsigned int order() const
Polynomial order of the shape functions.
Definition: serendipitylocalbasis.hh:334
void evaluateJacobian(const typename Traits::DomainType &in, std::vector< typename Traits::JacobianType > &out) const
Evaluate Jacobian of all shape functions.
Definition: serendipitylocalbasis.hh:214
void evaluate(const std::array< int, 1 > &direction, const typename Traits::DomainType &in, std::vector< typename Traits::RangeType > &out) const
Evaluate derivative in a given direction.
Definition: serendipitylocalbasis.hh:277
void evaluateFunction(const typename Traits::DomainType &in, std::vector< typename Traits::RangeType > &out) const
Evaluate all shape functions.
Definition: serendipitylocalbasis.hh:136
unsigned int size() const
number of shape functions
Definition: serendipitylocalbasis.hh:122