dune-composites (2.5.1)

serendipitylocalbasis.hh
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3
4#ifndef DUNE_LOCALFUNCTIONS_SERENDIPITYLOCALBASIS_HH
5#define DUNE_LOCALFUNCTIONS_SERENDIPITYLOCALBASIS_HH
6
7#include <dune/common/fvector.hh>
8#include <dune/common/fmatrix.hh>
9#include <dune/common/power.hh>
10
11#include <dune/geometry/type.hh>
12
13#include <dune/localfunctions/common/localbasis.hh>
14#include <dune/localfunctions/common/localfiniteelementtraits.hh>
15
16
17namespace Dune
18{
29 template<class D, class R, int k, int d>
31 {
32 typedef typename Dune::FieldVector<int,d> DuneVector;
33
34
35 // ith Lagrange polynomial of degree k in one dimension
36 static R p (int i,int deg, D x)
37 {
38 R result(1.0);
39 for (int j=0; j<=deg; j++)
40 if (j!=i) result *= (deg*x-j)/(i-j);
41 return result;
42 }
43
44 // derivative of ith Lagrange polynomial of degree k in one dimension
45 static R dp (int i, int deg, D x)
46 {
47 R result(0.0);
48
49 for (int j=0; j<=deg; j++)
50 if (j!=i)
51 {
52 R prod( (deg*1.0)/(i-j) );
53 for (int l=0; l<=deg; l++)
54 if (l!=i && l!=j)
55 prod *= (deg*x-l)/(i-l);
56 result += prod;
57 }
58 return result;
59 }
60
61 static void multiindex (DuneVector& alpha)
62 {
63 int i = 0;
64 for (int j=0; j<d; j++){
65 i+=alpha[j]*pow(k+1,j);
66 }
67 i++;
68 for (int j=0; j<d; j++)
69 {
70 alpha[j] = i % (k+1);
71 i = i/(k+1);
72 }
73 unsigned int sum = 0;
74 for (unsigned int j=0; j<d; j++){
75 if(alpha[j] > 0 && alpha[j] < k){ sum++; }
76 }
77 if(sum > 1){
78 multiindex(alpha);
79 }
80 }
81
82 bool isEdge(DuneVector& alpha) const{
83 for(int i = 0; i < d; i++){
84 if(alpha[i]>0 && alpha[i] < k)
85 return true;
86 }
87 return false;
88 }
89
90 double edgeVal(int alpha, const double& in, int der) const{
91 //add contribution from alpha
92 if(alpha > 0 && alpha < k){
93 if(der == 0)
94 return p(alpha,k,in);
95 else
96 return dp(alpha,k,in);
97 }
98 else{
99 if(der == 0)
100 return p(alpha/k,k-1,in);
101 else
102 return dp(alpha/k,k-1,in);
103 }
104 }
105
106 double nodeVal(int alpha, const double& in, int der) const{
107 // (k-1)-th order component
108 if(k == 1 && der == 0)
109 return p(alpha,k,in);
110 if(k == 1 && der > 0)
111 return dp(alpha,k, in);
112 if(der == 0)
113 return p(alpha/k,k-1,in);
114 else
115 return dp(alpha/k,k-1,in);
116 }
117
118 public:
119 typedef LocalBasisTraits<D,d,Dune::FieldVector<D,d>,R,1,Dune::FieldVector<R,1>,Dune::FieldMatrix<R,1,d>, 1> Traits;
120
122 unsigned int size () const
123 {
124 if(d == 1){
125 return k+1;
126 }
127 if(d == 2){
128 return 2*(k+1)+2*(k-1);
129 }
130 if(d == 3){
131 return 4*(k+1)+8*(k-1);
132 }
133 }
134
136 inline void evaluateFunction (const typename Traits::DomainType& in,
137 std::vector<typename Traits::RangeType>& out) const
138 {
139 DuneVector alpha(0);
140 out.resize(size());
141 for (size_t i=0; i<size(); i++)
142 {
143 // convert index i to multiindex
144 if(i>0){ multiindex(alpha); }
145
146 out[i] = 1.0;
147 for(int j = 0; j < d; j++){
148 if(isEdge(alpha))
149 out[i] *= edgeVal(alpha[j], in[j], 0);
150 else{ //isNode
151 out[i] *= nodeVal(alpha[j], in[j], 0);
152 }
153 }
154 }
155 if(k==2){
156 if(d==2){
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]);
161 }
162 if(d==3){
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]);
171 }
172 }
173
174 //========================Debug test===========================
175 /*for(size_t h =0; h < 9; h++){
176 Dune::FieldVector<double,d> inh = {(h%3)/2.0,((h/3)%3)/2.0};
177 std::cout << "At point " << inh << std::endl;
178
179 Dune::FieldVector<double,8> outh;
180 DuneVector alpha(0);
181 for (size_t i=0; i<size(); i++)
182 {
183 // convert index i to multiindex
184 if(i>0){ multiindex(alpha); }
185
186 outh[i] = 1.0;
187 for(int j = 0; j < d; j++){
188 if(isEdge(alpha))
189 outh[i] *= edgeVal(alpha[j], inh[j], 0);
190 else{ //isNode
191 outh[i] *= nodeVal(alpha[j], inh[j], 0);
192 }
193 }
194 }
195 if(d==2){
196 outh[0] = outh[0] - 0.5*(outh[1]+outh[3]);
197 outh[2] = outh[2] - 0.5*(outh[1]+outh[4]);
198 outh[5] = outh[5] - 0.5*(outh[3]+outh[6]);
199 outh[7] = outh[7] - 0.5*(outh[4]+outh[6]);
200 }
201
202 for (size_t i=0; i<size(); i++)
203 std::cout << " value " << i << " is " << outh[i] << std::endl;
204 }*/
205 //===================End======================================
206
207 }
208
213 inline void
214 evaluateJacobian (const typename Traits::DomainType& in,
215 std::vector<typename Traits::JacobianType>& out) const
216 {
217 out.resize(size());
218 DuneVector alpha(0);
219
220 // Loop over all shape functions
221 for (size_t i=0; i<size(); i++)
222 {
223 // convert index i to multiindex
224 if(i>0){ multiindex(alpha); }
225
226 out[i] =1.0;
227 // Loop over all coordinate directions
228 for (int j=0; j<d; j++)
229 {
230 // Initialize: the overall expression is a product
231 // if j-th bit of i is set to -1, else 1
232 if(isEdge(alpha))
233 out[i][0][j] *= edgeVal(alpha[j],in[j], 1);
234 else
235 out[i][0][j] *= nodeVal(alpha[j],in[j], 1);
236 // rest of the product
237 for (int l=0; l<d; l++){
238 if (l!=j){
239 if(isEdge(alpha))
240 out[i][0][j] *= edgeVal(alpha[l],in[l],0);
241 else
242 out[i][0][j] *= nodeVal(alpha[l],in[l],0);
243 }
244 }
245 }
246 }
247 if(k==2){
248 if(d==2){
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]);
254 }
255 }
256 if(d==3){
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]);
266 }
267 }
268 }
269 }
270
276 template<int diffOrder>
277 inline void evaluate(
278 const std::array<int,1>& direction,
279 const typename Traits::DomainType& in,
280 std::vector<typename Traits::RangeType>& out) const
281 {
282 static_assert(diffOrder == 1, "We only can compute first derivatives");
283 out.resize(size());
284 DuneVector alpha(0);
285
286 // Loop over all shape functions
287 for (size_t i=0; i<size(); i++)
288 {
289 // convert index i to multiindex
290 if(i>0){ multiindex(alpha);}
291
292 // Loop over all coordinate directions
293 std::size_t j = direction[0];
294
295 out[i] =1.0;
296 // Initialize: the overall expression is a product
297 // if j-th bit of i is set to -1, else 1
298 if(isEdge(alpha))
299 out[i][0] *= edgeVal(alpha[j],in[j],1);
300 else
301 out[i][0] *= nodeVal(alpha[j],in[j],1);
302
303 // rest of the product
304 for (std::size_t l=0; l<d; l++){
305 if (l!=j){
306 if(isEdge(alpha))
307 out[i][0] *= edgeVal(alpha[l],in[l],0);
308 else
309 out[i][0] *= nodeVal(alpha[l],in[l],0);
310 }
311 }
312 }
313 if(k==2){
314 if(d==2){
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]);
319 }
320 if(d==3){
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]);
329 }
330 }
331 }
332
334 unsigned int order () const
335 {
336 return k;
337 }
338 };
339}
340
341#endif
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
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden & Uni Heidelberg  |  generated with Hugo v0.111.3 (Sep 4, 22:38, 2025)