dune-localfunctions 2.12-git
Loading...
Searching...
No Matches
lagrangeprism.hh
Go to the documentation of this file.
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
4// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
5#ifndef DUNE_LOCALFUNCTIONS_LAGRANGE_LAGRANGEPRISM_HH
6#define DUNE_LOCALFUNCTIONS_LAGRANGE_LAGRANGEPRISM_HH
7
8#include <array>
9#include <numeric>
10
13#include <dune/common/math.hh>
14
16
21
22namespace Dune { namespace Impl
23{
24
25 // The traits provide static or dynamic order and size information
26 template<int compileTimeOrder>
27 struct LagrangePrismOrderTraits;
28
29 // The traits provide static order and size information
30 template<int compileTimeOrder>
31 requires (compileTimeOrder >= 0)
32 struct LagrangePrismOrderTraits<compileTimeOrder>
33 {
34 static constexpr bool is_static_order = true;
35
36 constexpr LagrangePrismOrderTraits(int /*runTimeOrder*/ = compileTimeOrder)
37 {
38 static_assert((0 <= compileTimeOrder) and (compileTimeOrder <= 2), "LagrangePrism: Only order 0,1, and 2 are supported");
39 }
40
44 static constexpr unsigned int order() {
45 return compileTimeOrder;
46 }
47
51 static constexpr std::size_t size() {
52 return binomial(compileTimeOrder+2,2) * (compileTimeOrder+1);
53 }
54 };
55
56
57 // this specialization is for the dynamic order case
58 template<>
59 struct LagrangePrismOrderTraits<-1>
60 {
61 unsigned int runTimeOrder_;
62 unsigned int size_;
63
64 static constexpr bool is_static_order = false;
65
66 constexpr explicit LagrangePrismOrderTraits(int runTimeOrder)
67 : runTimeOrder_(runTimeOrder >= 0 ? (unsigned int)(runTimeOrder) : 0u)
68 , size_(binomial(runTimeOrder+2,2) * (runTimeOrder+1))
69 {
70 if ((runTimeOrder < 0) or (runTimeOrder > 2))
71 DUNE_THROW(Dune::InvalidStateException, "LagrangePrism: Only order 0,1, and 2 are supported");
72 }
73
77 constexpr unsigned int order() const
78 {
79 return runTimeOrder_;
80 }
81
85 constexpr std::size_t size() const
86 {
87 return size_;
88 }
89 };
90
100 template<class D, class R, int compileTimeOrder>
101 class LagrangePrismLocalBasis
102 : public LagrangePrismOrderTraits<compileTimeOrder>
103 {
104 using OrderTraits = LagrangePrismOrderTraits<compileTimeOrder>;
105 static constexpr std::size_t dim = 3;
106 public:
107 using Traits = LocalBasisTraits<D,dim,FieldVector<D,dim>,R,1,FieldVector<R,1>,FieldMatrix<R,1,dim> >;
108
109 constexpr LagrangePrismLocalBasis(OrderTraits orderTraits)
110 : OrderTraits(orderTraits)
111 {}
112
113 using OrderTraits::order;
114 using OrderTraits::size;
115
117 void evaluateFunction(const typename Traits::DomainType& in,
119 {
120 out.resize(size());
121
122 // Specialization for zero-order case
123 if (order()==0)
124 {
125 out[0] = 1;
126 return;
127 }
128
129 if (order()==1)
130 {
131 out[0] = (1.0-in[0]-in[1])*(1.0-in[2]);
132 out[1] = in[0]*(1-in[2]);
133 out[2] = in[1]*(1-in[2]);
134 out[3] = in[2]*(1.0-in[0]-in[1]);
135 out[4] = in[0]*in[2];
136 out[5] = in[1]*in[2];
137
138 return;
139 }
140
141 if (order()==2)
142 {
143 FieldVector<R,3> segmentShapeFunction;
144 segmentShapeFunction[0] = 1 + in[2] * (-3 + 2*in[2]);
145 segmentShapeFunction[1] = in[2] * (4 - 4*in[2]);
146 segmentShapeFunction[2] = in[2] * (-1 + 2*in[2]);
147
148 FieldVector<R, 6> triangleShapeFunction;
149 triangleShapeFunction[0] = 2 * (1 - in[0] - in[1]) * (0.5 - in[0] - in[1]);
150 triangleShapeFunction[1] = 2 * in[0] * (-0.5 + in[0]);
151 triangleShapeFunction[2] = 2 * in[1] * (-0.5 + in[1]);
152 triangleShapeFunction[3] = 4*in[0] * (1 - in[0] - in[1]);
153 triangleShapeFunction[4] = 4*in[1] * (1 - in[0] - in[1]);
154 triangleShapeFunction[5] = 4*in[0]*in[1];
155
156 // lower triangle:
157 out[0] = triangleShapeFunction[0] * segmentShapeFunction[0];
158 out[1] = triangleShapeFunction[1] * segmentShapeFunction[0];
159 out[2] = triangleShapeFunction[2] * segmentShapeFunction[0];
160
161 //upper triangle
162 out[3] = triangleShapeFunction[0] * segmentShapeFunction[2];
163 out[4] = triangleShapeFunction[1] * segmentShapeFunction[2];
164 out[5] = triangleShapeFunction[2] * segmentShapeFunction[2];
165
166 // vertical edges
167 out[6] = triangleShapeFunction[0] * segmentShapeFunction[1];
168 out[7] = triangleShapeFunction[1] * segmentShapeFunction[1];
169 out[8] = triangleShapeFunction[2] * segmentShapeFunction[1];
170
171 // lower triangle edges
172 out[9] = triangleShapeFunction[3] * segmentShapeFunction[0];
173 out[10] = triangleShapeFunction[4] * segmentShapeFunction[0];
174 out[11] = triangleShapeFunction[5] * segmentShapeFunction[0];
175
176 // upper triangle edges
177 out[12] = triangleShapeFunction[3] * segmentShapeFunction[2];
178 out[13] = triangleShapeFunction[4] * segmentShapeFunction[2];
179 out[14] = triangleShapeFunction[5] * segmentShapeFunction[2];
180
181 // quadrilateral sides
182 out[15] = triangleShapeFunction[3] * segmentShapeFunction[1];
183 out[16] = triangleShapeFunction[4] * segmentShapeFunction[1];
184 out[17] = triangleShapeFunction[5] * segmentShapeFunction[1];
185
186 return;
187 }
188
189 DUNE_THROW(NotImplemented, "LagrangePrismLocalBasis::evaluateFunction for order " << order());
190 }
191
197 void evaluateJacobian(const typename Traits::DomainType& in,
199 {
200 out.resize(size());
201
202 // Specialization for k==0
203 if (order()==0)
204 {
205 std::fill(out[0][0].begin(), out[0][0].end(), 0);
206 return;
207 }
208
209 if (order()==1)
210 {
211 out[0][0] = {in[2]-1, in[2]-1, in[0]+in[1]-1};
212 out[1][0] = {1-in[2], 0, -in[0]};
213 out[2][0] = { 0, 1-in[2], -in[1]};
214 out[3][0] = { -in[2], -in[2], 1-in[0]-in[1]};
215 out[4][0] = { in[2], 0, in[0]};
216 out[5][0] = { 0, in[2], in[1]};
217
218 return;
219 }
220
221 if (order()==2)
222 {
223 // Second-order shape functions on a triangle, and the first derivatives
224 FieldVector<R, 6> triangleShapeFunction;
225 triangleShapeFunction[0] = 2 * (1 - in[0] - in[1]) * (0.5 - in[0] - in[1]);
226 triangleShapeFunction[1] = 2 * in[0] * (-0.5 + in[0]);
227 triangleShapeFunction[2] = 2 * in[1] * (-0.5 + in[1]);
228 triangleShapeFunction[3] = 4*in[0] * (1 - in[0] - in[1]);
229 triangleShapeFunction[4] = 4*in[1] * (1 - in[0] - in[1]);
230 triangleShapeFunction[5] = 4*in[0]*in[1];
231
232 std::array<std::array<R,2>,6> triangleShapeFunctionDer;
233 triangleShapeFunctionDer[0] = {-3 + 4*(in[0] + in[1]), -3 + 4*(in[0] + in[1])};
234 triangleShapeFunctionDer[1] = { -1 + 4*in[0], 0};
235 triangleShapeFunctionDer[2] = { 0, -1 + 4*in[1]};
236 triangleShapeFunctionDer[3] = { 4 - 8*in[0] - 4*in[1], -4*in[0]};
237 triangleShapeFunctionDer[4] = { -4*in[1], 4 - 4*in[0] - 8*in[1]};
238 triangleShapeFunctionDer[5] = { 4*in[1], 4*in[0]};
239
240 // Second-order shape functions on a line, and the first derivatives
241 FieldVector<R,3> segmentShapeFunction;
242 segmentShapeFunction[0] = 1 + in[2] * (-3 + 2*in[2]);
243 segmentShapeFunction[1] = in[2] * ( 4 - 4*in[2]);
244 segmentShapeFunction[2] = in[2] * (-1 + 2*in[2]);
245
246 FieldVector<R,3> segmentShapeFunctionDer;
247 segmentShapeFunctionDer[0] = -3 + 4*in[2];
248 segmentShapeFunctionDer[1] = 4 - 8*in[2];
249 segmentShapeFunctionDer[2] = -1 + 4*in[2];
250
251 // lower triangle:
252 out[0][0][0] = triangleShapeFunctionDer[0][0] * segmentShapeFunction[0];
253 out[0][0][1] = triangleShapeFunctionDer[0][1] * segmentShapeFunction[0];
254 out[0][0][2] = triangleShapeFunction[0] * segmentShapeFunctionDer[0];
255
256 out[1][0][0] = triangleShapeFunctionDer[1][0] * segmentShapeFunction[0];
257 out[1][0][1] = triangleShapeFunctionDer[1][1] * segmentShapeFunction[0];
258 out[1][0][2] = triangleShapeFunction[1] * segmentShapeFunctionDer[0];
259
260 out[2][0][0] = triangleShapeFunctionDer[2][0] * segmentShapeFunction[0];
261 out[2][0][1] = triangleShapeFunctionDer[2][1] * segmentShapeFunction[0];
262 out[2][0][2] = triangleShapeFunction[2] * segmentShapeFunctionDer[0];
263
264 //upper triangle
265 out[3][0][0] = triangleShapeFunctionDer[0][0] * segmentShapeFunction[2];
266 out[3][0][1] = triangleShapeFunctionDer[0][1] * segmentShapeFunction[2];
267 out[3][0][2] = triangleShapeFunction[0] * segmentShapeFunctionDer[2];
268
269 out[4][0][0] = triangleShapeFunctionDer[1][0] * segmentShapeFunction[2];
270 out[4][0][1] = triangleShapeFunctionDer[1][1] * segmentShapeFunction[2];
271 out[4][0][2] = triangleShapeFunction[1] * segmentShapeFunctionDer[2];
272
273 out[5][0][0] = triangleShapeFunctionDer[2][0] * segmentShapeFunction[2];
274 out[5][0][1] = triangleShapeFunctionDer[2][1] * segmentShapeFunction[2];
275 out[5][0][2] = triangleShapeFunction[2] * segmentShapeFunctionDer[2];
276
277 // vertical edges
278 out[6][0][0] = triangleShapeFunctionDer[0][0] * segmentShapeFunction[1];
279 out[6][0][1] = triangleShapeFunctionDer[0][1] * segmentShapeFunction[1];
280 out[6][0][2] = triangleShapeFunction[0] * segmentShapeFunctionDer[1];
281
282 out[7][0][0] = triangleShapeFunctionDer[1][0] * segmentShapeFunction[1];
283 out[7][0][1] = triangleShapeFunctionDer[1][1] * segmentShapeFunction[1];
284 out[7][0][2] = triangleShapeFunction[1] * segmentShapeFunctionDer[1];
285
286 out[8][0][0] = triangleShapeFunctionDer[2][0] * segmentShapeFunction[1];
287 out[8][0][1] = triangleShapeFunctionDer[2][1] * segmentShapeFunction[1];
288 out[8][0][2] = triangleShapeFunction[2] * segmentShapeFunctionDer[1];
289
290 // lower triangle edges
291 out[9][0][0] = triangleShapeFunctionDer[3][0] * segmentShapeFunction[0];
292 out[9][0][1] = triangleShapeFunctionDer[3][1] * segmentShapeFunction[0];
293 out[9][0][2] = triangleShapeFunction[3] * segmentShapeFunctionDer[0];
294
295 out[10][0][0] = triangleShapeFunctionDer[4][0] * segmentShapeFunction[0];
296 out[10][0][1] = triangleShapeFunctionDer[4][1] * segmentShapeFunction[0];
297 out[10][0][2] = triangleShapeFunction[4] * segmentShapeFunctionDer[0];
298
299 out[11][0][0] = triangleShapeFunctionDer[5][0] * segmentShapeFunction[0];
300 out[11][0][1] = triangleShapeFunctionDer[5][1] * segmentShapeFunction[0];
301 out[11][0][2] = triangleShapeFunction[5] * segmentShapeFunctionDer[0];
302
303 // upper triangle edges
304 out[12][0][0] = triangleShapeFunctionDer[3][0] * segmentShapeFunction[2];
305 out[12][0][1] = triangleShapeFunctionDer[3][1] * segmentShapeFunction[2];
306 out[12][0][2] = triangleShapeFunction[3] * segmentShapeFunctionDer[2];
307
308 out[13][0][0] = triangleShapeFunctionDer[4][0] * segmentShapeFunction[2];
309 out[13][0][1] = triangleShapeFunctionDer[4][1] * segmentShapeFunction[2];
310 out[13][0][2] = triangleShapeFunction[4] * segmentShapeFunctionDer[2];
311
312 out[14][0][0] = triangleShapeFunctionDer[5][0] * segmentShapeFunction[2];
313 out[14][0][1] = triangleShapeFunctionDer[5][1] * segmentShapeFunction[2];
314 out[14][0][2] = triangleShapeFunction[5] * segmentShapeFunctionDer[2];
315
316 // quadrilateral sides
317 out[15][0][0] = triangleShapeFunctionDer[3][0] * segmentShapeFunction[1];
318 out[15][0][1] = triangleShapeFunctionDer[3][1] * segmentShapeFunction[1];
319 out[15][0][2] = triangleShapeFunction[3] * segmentShapeFunctionDer[1];
320
321 out[16][0][0] = triangleShapeFunctionDer[4][0] * segmentShapeFunction[1];
322 out[16][0][1] = triangleShapeFunctionDer[4][1] * segmentShapeFunction[1];
323 out[16][0][2] = triangleShapeFunction[4] * segmentShapeFunctionDer[1];
324
325 out[17][0][0] = triangleShapeFunctionDer[5][0] * segmentShapeFunction[1];
326 out[17][0][1] = triangleShapeFunctionDer[5][1] * segmentShapeFunction[1];
327 out[17][0][2] = triangleShapeFunction[5] * segmentShapeFunctionDer[1];
328
329 return;
330 }
331
332 DUNE_THROW(NotImplemented, "LagrangePrismLocalBasis::evaluateJacobian for order " << order());
333 }
334
341 void partial(const std::array<unsigned int,dim>& order,
342 const typename Traits::DomainType& in,
344 {
345 auto totalOrder = std::accumulate(order.begin(), order.end(), 0);
346
347 out.resize(size());
348
349 if (totalOrder == 0)
350 {
351 evaluateFunction(in, out);
352 return;
353 }
354
355 // Specialization for zero-order finite elements
356 if (OrderTraits::order()==0)
357 {
358 out[0] = 0;
359 return;
360 }
361
362 // Specialization for first-order finite elements
363 if (OrderTraits::order()==1)
364 {
365 if (totalOrder == 1)
366 {
367 auto direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 1));
368
369 switch (direction) {
370 case 0:
371 out[0] = in[2]-1;
372 out[1] = 1-in[2];
373 out[2] = 0;
374 out[3] = -in[2];
375 out[4] = in[2];
376 out[5] = 0;
377 break;
378 case 1:
379 out[0] = in[2]-1;
380 out[1] = 0;
381 out[2] = 1-in[2];
382 out[3] = -in[2];
383 out[4] = 0;
384 out[5] = in[2];
385 break;
386 case 2:
387 out[0] = in[0]+in[1]-1;
388 out[1] = -in[0];
389 out[2] = -in[1];
390 out[3] = 1-in[0]-in[1];
391 out[4] = in[0];
392 out[5] = in[1];
393 break;
394 default:
395 DUNE_THROW(RangeError, "Component out of range.");
396 }
397 } else if (totalOrder == 2) {
398 out.resize(size());
399 if (order[0] == 1 && order[2] == 1) {
400 out[0] = 1;
401 out[1] =-1;
402 out[2] = 0;
403 out[3] =-1;
404 out[4] = 1;
405 out[5] = 0;
406 } else if (order[1] == 1 && order[2] == 1) {
407 out[0] = 1;
408 out[1] = 0;
409 out[2] =-1;
410 out[3] =-1;
411 out[4] = 0;
412 out[5] = 1;
413 } else {
414 for (std::size_t i = 0; i < size(); ++i)
415 out[i] = 0;
416 }
417 } else {
418 out.resize(size());
419 std::fill(out.begin(), out.end(), 0.0);
420 }
421
422 return;
423 }
424
425 // Specialization for second-order finite elements
426 if (OrderTraits::order()==2)
427 {
428 if (totalOrder == 1)
429 {
430 auto const direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 1));
431 switch (direction)
432 {
433 case 0:
434 {
435 FieldVector<R,6> triangleShapeFunctionDerX;
436 triangleShapeFunctionDerX[0] = -3 + 4*(in[0] + in[1]);
437 triangleShapeFunctionDerX[1] = -1 + 4* in[0];
438 triangleShapeFunctionDerX[2] = 0;
439 triangleShapeFunctionDerX[3] = 4 - 8* in[0] - 4*in[1];
440 triangleShapeFunctionDerX[4] = -4*in[1];
441 triangleShapeFunctionDerX[5] = 4*in[1];
442
443 FieldVector<R,3> segmentShapeFunction;
444 segmentShapeFunction[0] = 1 + in[2] * (-3 + 2*in[2]);
445 segmentShapeFunction[1] = in[2] * ( 4 - 4*in[2]);
446 segmentShapeFunction[2] = in[2] * (-1 + 2*in[2]);
447
448 out[0] = triangleShapeFunctionDerX[0] * segmentShapeFunction[0];
449 out[1] = triangleShapeFunctionDerX[1] * segmentShapeFunction[0];
450 out[2] = triangleShapeFunctionDerX[2] * segmentShapeFunction[0];
451 out[3] = triangleShapeFunctionDerX[0] * segmentShapeFunction[2];
452 out[4] = triangleShapeFunctionDerX[1] * segmentShapeFunction[2];
453 out[5] = triangleShapeFunctionDerX[2] * segmentShapeFunction[2];
454 out[6] = triangleShapeFunctionDerX[0] * segmentShapeFunction[1];
455 out[7] = triangleShapeFunctionDerX[1] * segmentShapeFunction[1];
456 out[8] = triangleShapeFunctionDerX[2] * segmentShapeFunction[1];
457 out[9] = triangleShapeFunctionDerX[3] * segmentShapeFunction[0];
458 out[10] = triangleShapeFunctionDerX[4] * segmentShapeFunction[0];
459 out[11] = triangleShapeFunctionDerX[5] * segmentShapeFunction[0];
460 out[12] = triangleShapeFunctionDerX[3] * segmentShapeFunction[2];
461 out[13] = triangleShapeFunctionDerX[4] * segmentShapeFunction[2];
462 out[14] = triangleShapeFunctionDerX[5] * segmentShapeFunction[2];
463 out[15] = triangleShapeFunctionDerX[3] * segmentShapeFunction[1];
464 out[16] = triangleShapeFunctionDerX[4] * segmentShapeFunction[1];
465 out[17] = triangleShapeFunctionDerX[5] * segmentShapeFunction[1];
466 break;
467 }
468 case 1:
469 {
470 FieldVector<R,6> triangleShapeFunctionDerY;
471 triangleShapeFunctionDerY[0] = -3 + 4*(in[0] + in[1]);
472 triangleShapeFunctionDerY[1] = 0;
473 triangleShapeFunctionDerY[2] = -1 + 4* in[1];
474 triangleShapeFunctionDerY[3] = -4* in[0];
475 triangleShapeFunctionDerY[4] = 4 - 4* in[0] - 8*in[1];
476 triangleShapeFunctionDerY[5] = 4* in[0];
477
478 FieldVector<R,3> segmentShapeFunction;
479 segmentShapeFunction[0] = 1 + in[2] * (-3 + 2*in[2]);
480 segmentShapeFunction[1] = in[2] * ( 4 - 4*in[2]);
481 segmentShapeFunction[2] = in[2] * (-1 + 2*in[2]);
482
483 out[0] = triangleShapeFunctionDerY[0] * segmentShapeFunction[0];
484 out[1] = triangleShapeFunctionDerY[1] * segmentShapeFunction[0];
485 out[2] = triangleShapeFunctionDerY[2] * segmentShapeFunction[0];
486 out[3] = triangleShapeFunctionDerY[0] * segmentShapeFunction[2];
487 out[4] = triangleShapeFunctionDerY[1] * segmentShapeFunction[2];
488 out[5] = triangleShapeFunctionDerY[2] * segmentShapeFunction[2];
489 out[6] = triangleShapeFunctionDerY[0] * segmentShapeFunction[1];
490 out[7] = triangleShapeFunctionDerY[1] * segmentShapeFunction[1];
491 out[8] = triangleShapeFunctionDerY[2] * segmentShapeFunction[1];
492 out[9] = triangleShapeFunctionDerY[3] * segmentShapeFunction[0];
493 out[10] = triangleShapeFunctionDerY[4] * segmentShapeFunction[0];
494 out[11] = triangleShapeFunctionDerY[5] * segmentShapeFunction[0];
495 out[12] = triangleShapeFunctionDerY[3] * segmentShapeFunction[2];
496 out[13] = triangleShapeFunctionDerY[4] * segmentShapeFunction[2];
497 out[14] = triangleShapeFunctionDerY[5] * segmentShapeFunction[2];
498 out[15] = triangleShapeFunctionDerY[3] * segmentShapeFunction[1];
499 out[16] = triangleShapeFunctionDerY[4] * segmentShapeFunction[1];
500 out[17] = triangleShapeFunctionDerY[5] * segmentShapeFunction[1];
501 break;
502 }
503 case 2:
504 {
505 FieldVector<R, 6> triangleShapeFunction;
506 triangleShapeFunction[0] = 2 * (1 - in[0] - in[1]) * (0.5 - in[0] - in[1]);
507 triangleShapeFunction[1] = 2 * in[0] * (-0.5 + in[0]);
508 triangleShapeFunction[2] = 2 * in[1] * (-0.5 + in[1]);
509 triangleShapeFunction[3] = 4*in[0] * (1 - in[0] - in[1]);
510 triangleShapeFunction[4] = 4*in[1] * (1 - in[0] - in[1]);
511 triangleShapeFunction[5] = 4*in[0]*in[1];
512
513 FieldVector<R,3> segmentShapeFunctionDer;
514 segmentShapeFunctionDer[0] = -3 + 4*in[2];
515 segmentShapeFunctionDer[1] = 4 - 8*in[2];
516 segmentShapeFunctionDer[2] = -1 + 4*in[2];
517
518 out[0] = triangleShapeFunction[0] * segmentShapeFunctionDer[0];
519 out[1] = triangleShapeFunction[1] * segmentShapeFunctionDer[0];
520 out[2] = triangleShapeFunction[2] * segmentShapeFunctionDer[0];
521 out[3] = triangleShapeFunction[0] * segmentShapeFunctionDer[2];
522 out[4] = triangleShapeFunction[1] * segmentShapeFunctionDer[2];
523 out[5] = triangleShapeFunction[2] * segmentShapeFunctionDer[2];
524 out[6] = triangleShapeFunction[0] * segmentShapeFunctionDer[1];
525 out[7] = triangleShapeFunction[1] * segmentShapeFunctionDer[1];
526 out[8] = triangleShapeFunction[2] * segmentShapeFunctionDer[1];
527 out[9] = triangleShapeFunction[3] * segmentShapeFunctionDer[0];
528 out[10] = triangleShapeFunction[4] * segmentShapeFunctionDer[0];
529 out[11] = triangleShapeFunction[5] * segmentShapeFunctionDer[0];
530 out[12] = triangleShapeFunction[3] * segmentShapeFunctionDer[2];
531 out[13] = triangleShapeFunction[4] * segmentShapeFunctionDer[2];
532 out[14] = triangleShapeFunction[5] * segmentShapeFunctionDer[2];
533 out[15] = triangleShapeFunction[3] * segmentShapeFunctionDer[1];
534 out[16] = triangleShapeFunction[4] * segmentShapeFunctionDer[1];
535 out[17] = triangleShapeFunction[5] * segmentShapeFunctionDer[1];
536 break;
537 }
538 default:
539 DUNE_THROW(RangeError, "Component out of range.");
540 }
541 } else {
542 DUNE_THROW(NotImplemented, "Desired derivative order is not implemented");
543 }
544
545 return;
546 }
547
548 DUNE_THROW(NotImplemented, "LagrangePrismLocalBasis::partial not implemented for order " << OrderTraits::order());
549 }
550
551 };
552
557 template<int compileTimeOrder>
558 class LagrangePrismLocalCoefficients
559 : public LagrangePrismOrderTraits<compileTimeOrder>
560 {
561 using OrderTraits = LagrangePrismOrderTraits<compileTimeOrder>;
562 public:
563
564 using OrderTraits::order;
565 using OrderTraits::size;
566
568 LagrangePrismLocalCoefficients (OrderTraits orderTraits)
569 : OrderTraits(orderTraits)
570 , localKeys_(size())
571 {
572 if (order()==0)
573 {
574 localKeys_[0] = LocalKey(0,0,0);
575 return;
576 }
577
578 if (order()==1)
579 {
580 for (std::size_t i=0; i<size(); i++)
581 localKeys_[i] = LocalKey(i,3,0);
582 return;
583 }
584
585 if (order()==2)
586 {
587 // Vertex shape functions
588 localKeys_[0] = LocalKey(0,3,0);
589 localKeys_[1] = LocalKey(1,3,0);
590 localKeys_[2] = LocalKey(2,3,0);
591 localKeys_[3] = LocalKey(3,3,0);
592 localKeys_[4] = LocalKey(4,3,0);
593 localKeys_[5] = LocalKey(5,3,0);
594
595 // Edge shape functions
596 localKeys_[6] = LocalKey(0,2,0);
597 localKeys_[7] = LocalKey(1,2,0);
598 localKeys_[8] = LocalKey(2,2,0);
599 localKeys_[9] = LocalKey(3,2,0);
600 localKeys_[10] = LocalKey(4,2,0);
601 localKeys_[11] = LocalKey(5,2,0);
602 localKeys_[12] = LocalKey(6,2,0);
603 localKeys_[13] = LocalKey(7,2,0);
604 localKeys_[14] = LocalKey(8,2,0);
605
606 // Quadrilateral sides shape functions
607 localKeys_[15] = LocalKey(0,1,0);
608 localKeys_[16] = LocalKey(1,1,0);
609 localKeys_[17] = LocalKey(2,1,0);
610
611 return;
612 }
613
614 // Now: the general case
615 DUNE_THROW(NotImplemented, "LagrangePrismLocalCoefficients not implemented for order " << order());
616
617 }
618
619 LagrangePrismLocalCoefficients ()
620 requires(OrderTraits::is_static_order)
621 : LagrangePrismLocalCoefficients(OrderTraits())
622 {}
623
624
626 const LocalKey& localKey (std::size_t i) const
627 {
628 return localKeys_[i];
629 }
630
631 private:
632 std::vector<LocalKey> localKeys_;
633 };
634
639 template<class D, class R, int compileTimeOrder>
640 class LagrangePrismLocalInterpolation
641 : public LagrangePrismOrderTraits<compileTimeOrder>
642 {
643 using Traits = typename LagrangePrismLocalBasis<D,R,compileTimeOrder>::Traits;
644 using OrderTraits = LagrangePrismOrderTraits<compileTimeOrder>;
645 public:
646
647 constexpr LagrangePrismLocalInterpolation(OrderTraits orderTraits)
648 : OrderTraits(orderTraits)
649 {}
650
658 template<typename F, typename C>
659 void interpolate (const F& f, std::vector<C>& out) const
660 {
661 constexpr auto dim = Traits::dimDomain;
662 auto k = OrderTraits::order();
663 using Domain = typename Traits::DomainType;
664 using DomainField = typename Traits::DomainFieldType;
665
666 out.resize(OrderTraits::size());
667
668 // Specialization for zero-order case
669 if (k==0)
670 {
671 auto center = ReferenceElements<DomainField,dim>::general(GeometryTypes::prism).position(0,0);
672 out[0] = Impl::rangeCast(f(center));
673 return;
674 }
675
676 // Specialization for first-order case
677 if (k==1)
678 {
679 for (unsigned int i=0; i<OrderTraits::size(); i++)
680 {
681 auto vertex = ReferenceElements<DomainField,3>::general(GeometryTypes::prism).position(i,3);
682 out[i] = Impl::rangeCast(f(vertex));
683 }
684 return;
685 }
686
687 if (k==2)
688 {
689 out[0] = Impl::rangeCast( f( Domain( {0.0, 0.0, 0.0} ) ) );
690 out[1] = Impl::rangeCast( f( Domain( {1.0, 0.0, 0.0} ) ) );
691 out[2] = Impl::rangeCast( f( Domain( {0.0, 1.0, 0.0} ) ) );
692 out[3] = Impl::rangeCast( f( Domain( {0.0, 0.0, 1.0} ) ) );
693 out[4] = Impl::rangeCast( f( Domain( {1.0, 0.0, 1.0} ) ) );
694 out[5] = Impl::rangeCast( f( Domain( {0.0, 1.0, 1.0} ) ) );
695 out[6] = Impl::rangeCast( f( Domain( {0.0, 0.0, 0.5} ) ) );
696 out[7] = Impl::rangeCast( f( Domain( {1.0, 0.0, 0.5} ) ) );
697 out[8] = Impl::rangeCast( f( Domain( {0.0, 1.0, 0.5} ) ) );
698 out[9] = Impl::rangeCast( f( Domain( {0.5, 0.0, 0.0} ) ) );
699 out[10] = Impl::rangeCast( f( Domain( {0.0, 0.5, 0.0} ) ) );
700 out[11] = Impl::rangeCast( f( Domain( {0.5, 0.5, 0.0} ) ) );
701 out[12] = Impl::rangeCast( f( Domain( {0.5, 0.0, 1.0} ) ) );
702 out[13] = Impl::rangeCast( f( Domain( {0.0, 0.5, 1.0} ) ) );
703 out[14] = Impl::rangeCast( f( Domain( {0.5, 0.5, 1.0} ) ) );
704 out[15] = Impl::rangeCast( f( Domain( {0.5, 0.0, 0.5} ) ) );
705 out[16] = Impl::rangeCast( f( Domain( {0.0, 0.5, 0.5} ) ) );
706 out[17] = Impl::rangeCast( f( Domain( {0.5, 0.5, 0.5} ) ) );
707
708 return;
709 }
710
711 DUNE_THROW(NotImplemented, "LagrangePrismLocalInterpolation not implemented for order " << k);
712 }
713
714 };
715
716} } // namespace Dune::Impl
717
718namespace Dune
719{
726 template<class D, class R, int compileTimeOrder = -1>
728 : public Impl::LagrangePrismOrderTraits<compileTimeOrder>
729 {
730 using OrderTraits = Impl::LagrangePrismOrderTraits<compileTimeOrder>;
731 public:
732
736 Impl::LagrangePrismLocalCoefficients<compileTimeOrder>,
737 Impl::LagrangePrismLocalInterpolation<D,R,compileTimeOrder> >;
738
741 : OrderTraits()
742 , basis_(*this)
743 , coefficients_(*this)
744 , interpolation_(*this)
745 {
746 static_assert(OrderTraits::is_static_order, "Default constructor only allowed for compile-time >= 0");
747 static_assert((0 <= compileTimeOrder) and (compileTimeOrder <= 2), "LagrangePrism: Only order 0,1, and 2 are supported");
748 }
749
751 explicit constexpr LagrangePrismLocalFiniteElement(int runTimeOrder)
752 : OrderTraits(runTimeOrder)
753 , basis_(*this)
754 , coefficients_(*this)
755 , interpolation_(*this)
756 {
757 static_assert(not OrderTraits::is_static_order, "Passing a run-time order only allowed for compile-time = -1");
758 if ((runTimeOrder < 0) or (runTimeOrder > 2))
759 DUNE_THROW(Dune::InvalidStateException, "LagrangePrism: Only run-time order 0,1, and 2 are supported");
760 }
761
764 const typename Traits::LocalBasisType& localBasis () const
765 {
766 return basis_;
767 }
768
772 {
773 return coefficients_;
774 }
775
779 {
780 return interpolation_;
781 }
782
785 static constexpr GeometryType type ()
786 {
787 return GeometryTypes::prism;
788 }
789
790 private:
791 Impl::LagrangePrismLocalBasis<D,R,compileTimeOrder> basis_;
792 Impl::LagrangePrismLocalCoefficients<compileTimeOrder> coefficients_;
793 Impl::LagrangePrismLocalInterpolation<D,R,compileTimeOrder> interpolation_;
794 };
795
796} // namespace Dune
797
798#endif // DUNE_LOCALFUNCTIONS_LAGRANGE_LAGRANGEPRISM_HH
int size() const
iterator end()
iterator begin()
size_type dim() const
#define DUNE_THROW(E,...)
static constexpr T binomial(const T &n, const T &k) noexcept
D DomainType
domain type
Definition common/localbasis.hh:43
traits helper struct
Definition localfiniteelementtraits.hh:13
LB LocalBasisType
Definition localfiniteelementtraits.hh:16
LC LocalCoefficientsType
Definition localfiniteelementtraits.hh:20
LI LocalInterpolationType
Definition localfiniteelementtraits.hh:24
Lagrange finite element for 3d prisms with arbitrary compile-time polynomial order.
Definition lagrangeprism.hh:729
const Traits::LocalInterpolationType & localInterpolation() const
Returns object that evaluates degrees of freedom.
Definition lagrangeprism.hh:778
const Traits::LocalCoefficientsType & localCoefficients() const
Returns the assignment of the degrees of freedom to the element subentities.
Definition lagrangeprism.hh:771
static constexpr GeometryType type()
The reference element that the local finite element is defined on.
Definition lagrangeprism.hh:785
constexpr LagrangePrismLocalFiniteElement()
Constructor for compile-time order.
Definition lagrangeprism.hh:740
const Traits::LocalBasisType & localBasis() const
Returns the local basis, i.e., the set of shape functions.
Definition lagrangeprism.hh:764
constexpr LagrangePrismLocalFiniteElement(int runTimeOrder)
Constructor for run-time order.
Definition lagrangeprism.hh:751
T accumulate(T... args)
T begin(T... args)
T distance(T... args)
T end(T... args)
T fill(T... args)
T find(T... args)
T resize(T... args)