DUNE PDELab (unstable)

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