dune-localfunctions 2.12-git
Loading...
Searching...
No Matches
lagrangecube.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_LAGRANGECUBE_HH
6#define DUNE_LOCALFUNCTIONS_LAGRANGE_LAGRANGECUBE_HH
7
8#include <array>
9#include <numeric>
10
13#include <dune/common/math.hh>
15
17
22
23namespace Dune { namespace Impl
24{
25 // The traits provide static or dynamic order and size information
26 template<unsigned int dim, int compileTimeOrder>
27 struct LagrangeCubeOrderTraits;
28
29 // The traits provide static order and size information
30 template<unsigned int dim, int compileTimeOrder>
31 requires (compileTimeOrder >= 0)
32 struct LagrangeCubeOrderTraits<dim,compileTimeOrder>
33 {
34 static constexpr bool is_static_order = true;
35
36 constexpr LagrangeCubeOrderTraits(int /*runTimeOrder*/ = compileTimeOrder) {}
37
41 static constexpr std::size_t size ()
42 {
43 return power(compileTimeOrder+1, dim);
44 }
45
49 static constexpr unsigned int order ()
50 {
51 return compileTimeOrder;
52 }
53
54 // Return i as a d-digit number in the (k+1)-nary system
55 static constexpr std::array<unsigned int,dim> multiindex (unsigned int i)
56 {
58 for (unsigned int j=0; j<dim; j++)
59 {
60 alpha[j] = i % (order()+1);
61 i = i/(order()+1);
62 }
63 return alpha;
64 }
65 };
66
67
68 template<unsigned int dim>
69 struct LagrangeCubeOrderTraits<dim,-1>
70 {
71 unsigned int order_;
72 std::size_t size_;
73
74 static constexpr bool is_static_order = false;
75
79 constexpr LagrangeCubeOrderTraits (int runTimeOrder)
80 : order_(runTimeOrder >= 0 ? (unsigned int)(runTimeOrder) : 0u)
81 , size_(power(order_+1, dim))
82 {
83 if (runTimeOrder < 0)
84 DUNE_THROW(Dune::InvalidStateException, "LagrangeCube: run-time order must be >= 0");
85 }
86
90 constexpr std::size_t size () const
91 {
92 return size_;
93 }
94
98 constexpr unsigned int order () const
99 {
100 return order_;
101 }
102
103 // Return i as a d-digit number in the (k+1)-nary system
104 constexpr std::array<unsigned int,dim> multiindex (unsigned int i) const
105 {
107 for (unsigned int j=0; j<dim; j++)
108 {
109 alpha[j] = i % (order()+1);
110 i = i/(order()+1);
111 }
112 return alpha;
113 }
114 };
115
126 template<class D, class R, unsigned int dim, int compileTimeOrder>
127 class LagrangeCubeLocalBasis
128 : private LagrangeCubeOrderTraits<dim,compileTimeOrder>
129 {
130 using OrderTraits = LagrangeCubeOrderTraits<dim,compileTimeOrder>;
131
132 // i-th Lagrange polynomial of degree k in one dimension
133 constexpr R p (unsigned int i, D x) const
134 {
135 R result(1.0);
136 for (unsigned int j=0; j<=order(); j++)
137 if (j!=i) result *= (order()*x-j)/((int)i-(int)j);
138 return result;
139 }
140
141 // derivative of ith Lagrange polynomial of degree k in one dimension
142 constexpr R dp (unsigned int i, D x) const
143 {
144 R result(0.0);
145
146 for (unsigned int j=0; j<=order(); j++)
147 {
148 if (j!=i)
149 {
150 R prod( (order()*1.0)/((int)i-(int)j) );
151 for (unsigned int l=0; l<=order(); l++)
152 if (l!=i && l!=j)
153 prod *= (order()*x-l)/((int)i-(int)l);
154 result += prod;
155 }
156 }
157 return result;
158 }
159
160 // Second derivative of j-th Lagrange polynomial of degree k in one dimension
161 // Formula and notation taken from https://en.wikipedia.org/wiki/Lagrange_polynomial#Derivatives
162 constexpr R ddp(unsigned int j, D x) const
163 {
164 R result(0.0);
165
166 for (unsigned int i=0; i<=order(); i++)
167 {
168 if (i==j)
169 continue;
170
171 R sum(0);
172
173 for (unsigned int m=0; m<=order(); m++)
174 {
175 if (m==i || m==j)
176 continue;
177
178 R prod( (order()*1.0)/((int)j-(int)m) );
179 for (unsigned int l=0; l<=order(); l++)
180 if (l!=i && l!=j && l!=m)
181 prod *= (order()*x-l)/((int)j-(int)l);
182 sum += prod;
183 }
184
185 result += sum * ( (order()*1.0)/((int)j-(int)i) );
186 }
187
188 return result;
189 }
190
191 using OrderTraits::multiindex;
192
193 public:
194 using Traits = LocalBasisTraits<D,dim,FieldVector<D,dim>,R,1,FieldVector<R,1>,FieldMatrix<R,1,dim> >;
195
196 constexpr LagrangeCubeLocalBasis () requires (OrderTraits::is_static_order)
197 : OrderTraits()
198 {}
199
202 explicit constexpr LagrangeCubeLocalBasis (OrderTraits orderTraits)
203 : OrderTraits(orderTraits)
204 {}
205
206 using OrderTraits::size;
207 using OrderTraits::order;
208
210 constexpr void evaluateFunction (const typename Traits::DomainType& x,
212 {
213 out.resize(size());
214
215 // Specialization for zero-order case
216 if (order()==0)
217 {
218 out[0] = 1;
219 return;
220 }
221
222 if (order()==1)
223 {
224 for (size_t i=0; i<size(); i++)
225 {
226 out[i] = 1;
227
228 for (unsigned int j=0; j<dim; j++)
229 // if j-th bit of i is set multiply with x[j], else with 1-x[j]
230 out[i] *= (i & (1<<j)) ? x[j] : 1-x[j];
231 }
232 return;
233 }
234
235 // General case
236 for (size_t i=0; i<size(); i++)
237 {
238 // convert index i to multiindex
239 std::array<unsigned int,dim> alpha(multiindex(i));
240
241 // initialize product
242 out[i] = 1.0;
243
244 // dimension by dimension
245 for (unsigned int j=0; j<dim; j++)
246 out[i] *= p(alpha[j],x[j]);
247 }
248 }
249
255 constexpr void evaluateJacobian (const typename Traits::DomainType& x,
257 {
258 out.resize(size());
259
260 // Specialization for common case
261 if (order()==0)
262 {
263 std::fill(out[0][0].begin(), out[0][0].end(), 0);
264 return;
265 }
266
267 // Specialization for common case
268 if (order()==1)
269 {
270 // Loop over all shape functions
271 for (size_t i=0; i<size(); i++)
272 {
273 // Loop over all coordinate directions
274 for (unsigned int j=0; j<dim; j++)
275 {
276 // Initialize: the overall expression is a product
277 // if j-th bit of i is set to 1, else -11
278 out[i][0][j] = (i & (1<<j)) ? 1 : -1;
279
280 for (unsigned int l=0; l<dim; l++)
281 {
282 if (j!=l)
283 // if l-th bit of i is set multiply with x[l], else with 1-x[l]
284 out[i][0][j] *= (i & (1<<l)) ? x[l] : 1-x[l];
285 }
286 }
287 }
288 return;
289 }
290
291 // The general case
292
293 // Loop over all shape functions
294 for (size_t i=0; i<size(); i++)
295 {
296 // convert index i to multiindex
297 std::array<unsigned int,dim> alpha(multiindex(i));
298
299 // Loop over all coordinate directions
300 for (unsigned int j=0; j<dim; j++)
301 {
302 // Initialize: the overall expression is a product
303 // if j-th bit of i is set to -1, else 1
304 out[i][0][j] = dp(alpha[j],x[j]);
305
306 // rest of the product
307 for (unsigned int l=0; l<dim; l++)
308 if (l!=j)
309 out[i][0][j] *= p(alpha[l],x[l]);
310 }
311 }
312 }
313
320 constexpr void partial (const std::array<unsigned int,dim>& partialOrders,
321 const typename Traits::DomainType& in,
323 {
324 auto totalOrder = std::accumulate(partialOrders.begin(), partialOrders.end(), 0);
325
326 out.resize(size());
327
328 if (order()==0)
329 {
330 out[0] = (totalOrder==0);
331 return;
332 }
333
334 if (order()==1)
335 {
336 if (totalOrder == 0)
337 {
338 evaluateFunction(in, out);
339 }
340 else if (totalOrder == 1)
341 {
342 out.resize(size());
343
344 auto direction = std::distance(partialOrders.begin(),
345 std::find(partialOrders.begin(), partialOrders.end(), 1));
346 if (direction >= dim)
347 DUNE_THROW(RangeError, "Direction of partial derivative not found!");
348
349 // Loop over all shape functions
350 for (std::size_t i = 0; i < size(); ++i)
351 {
352 // Initialize: the overall expression is a product
353 // if j-th bit of i is set to 1, otherwise to -1
354 out[i] = (i & (1<<direction)) ? 1 : -1;
355
356 for (unsigned int j = 0; j < dim; ++j)
357 {
358 if (direction != j)
359 // if j-th bit of i is set multiply with in[j], else with 1-in[j]
360 out[i] *= (i & (1<<j)) ? in[j] : 1-in[j];
361 }
362 }
363 }
364 else if (totalOrder == 2)
365 {
366
367 for (size_t i=0; i<size(); i++)
368 {
369 // convert index i to multiindex
370 std::array<unsigned int,dim> alpha(multiindex(i));
371
372 // Initialize: the overall expression is a product
373 out[i][0] = 1.0;
374
375 // rest of the product
376 for (std::size_t l=0; l<dim; l++)
377 {
378 switch (partialOrders[l])
379 {
380 case 0:
381 out[i][0] *= p(alpha[l],in[l]);
382 break;
383 case 1:
384 //std::cout << "dp: " << dp(alpha[l],in[l]) << std::endl;
385 out[i][0] *= dp(alpha[l],in[l]);
386 break;
387 case 2:
388 out[i][0] *= 0;
389 break;
390 default:
391 DUNE_THROW(NotImplemented, "Desired derivative order is not implemented");
392 }
393 }
394 }
395 }
396 else
397 DUNE_THROW(NotImplemented, "Partial derivative of order " << totalOrder << " is not implemented!");
398
399 return;
400 }
401
402 // The case k>1
403
404 // Loop over all shape functions
405 for (size_t i=0; i<size(); i++)
406 {
407 // convert index i to multiindex
408 std::array<unsigned int,dim> alpha(multiindex(i));
409
410 // Initialize: the overall expression is a product
411 out[i][0] = 1.0;
412
413 // rest of the product
414 for (std::size_t l=0; l<dim; l++)
415 {
416 switch (partialOrders[l])
417 {
418 case 0:
419 out[i][0] *= p(alpha[l],in[l]);
420 break;
421 case 1:
422 out[i][0] *= dp(alpha[l],in[l]);
423 break;
424 case 2:
425 out[i][0] *= ddp(alpha[l],in[l]);
426 break;
427 default:
428 DUNE_THROW(NotImplemented, "Desired derivative order is not implemented");
429 }
430 }
431 }
432 }
433 };
434
440 template<unsigned int dim, int compileTimeOrder>
441 class LagrangeCubeLocalCoefficients
442 : private LagrangeCubeOrderTraits<dim,compileTimeOrder>
443 {
444 using OrderTraits = LagrangeCubeOrderTraits<dim,compileTimeOrder>;
445
446 using OrderTraits::multiindex;
447
449 void setup1d (std::vector<unsigned int>& subEntity)
450 {
451 const unsigned int k = order();
452 assert(k>0);
453
454 unsigned lastIndex=0;
455
456 /* edge and vertex numbering
457 0----0----1
458 */
459
460 // edge (0)
461 subEntity[lastIndex++] = 0; // corner 0
462 for (unsigned i = 0; i < k - 1; ++i)
463 subEntity[lastIndex++] = 0; // inner dofs of element (0)
464
465 subEntity[lastIndex++] = 1; // corner 1
466
467 assert(power(k+1,dim)==lastIndex);
468 }
469
470 void setup2d (std::vector<unsigned int>& subEntity)
471 {
472 const unsigned int k = order();
473 assert(k>0);
474
475 unsigned lastIndex=0;
476
477 // LocalKey: entity number, entity codim, dof indices within each entity
478 /* edge and vertex numbering
479 2----3----3
480 | |
481 | |
482 0 1
483 | |
484 | |
485 0----2----1
486 */
487
488 // lower edge (2)
489 subEntity[lastIndex++] = 0; // corner 0
490 for (unsigned i = 0; i < k - 1; ++i)
491 subEntity[lastIndex++] = 2; // inner dofs of lower edge (2)
492
493 subEntity[lastIndex++] = 1; // corner 1
494
495 // iterate from bottom to top over inner edge dofs
496 for (unsigned e = 0; e < k - 1; ++e) {
497 subEntity[lastIndex++] = 0; // left edge (0)
498 for (unsigned i = 0; i < k - 1; ++i)
499 subEntity[lastIndex++] = 0; // face dofs
500 subEntity[lastIndex++] = 1; // right edge (1)
501 }
502
503 // upper edge (3)
504 subEntity[lastIndex++] = 2; // corner 2
505 for (unsigned i = 0; i < k - 1; ++i)
506 subEntity[lastIndex++] = 3; // inner dofs of upper edge (3)
507
508 subEntity[lastIndex++] = 3; // corner 3
509
510 assert(power(k+1,dim)==lastIndex);
511 }
512
513 void setup3d (std::vector<unsigned int>& subEntity)
514 {
515 const unsigned int k = order();
516 assert(k>0);
517
518 unsigned lastIndex=0;
519#ifndef NDEBUG
520 const unsigned numIndices = power(k+1,dim);
521 const unsigned numFaceIndices = power(k+1,dim-1);
522#endif
523 const unsigned numInnerEdgeDofs = k-1;
524
525 // LocalKey: entity number, entity codim, dof indices within each entity
526 /* edge and vertex numbering
527
528 6---(11)--7 6---------7
529 /| /| /| (5) /|
530 (8)| (9)| / | top / |
531 / (2) / (3) / |(3)bac/k |
532 4---(10)--5 | 4---------5 |
533 | | | | left|(0)| |(1)|right
534 | 2--(7)|---3 | 2-----|---3
535 (0) / (1) / |(2)front | /
536 |(4) |(5) | / (4) | /
537 |/ |/ |/ bottom |/
538 0---(6)---1 0---------1
539 */
540
541 // bottom face (4)
542 lastIndex=0;
543 // lower edge (6)
544 subEntity[lastIndex++] = 0; // corner 0
545 for (unsigned i = 0; i < numInnerEdgeDofs; ++i)
546 subEntity[lastIndex++] = 6; // inner dofs of lower edge (6)
547
548 subEntity[lastIndex++] = 1; // corner 1
549
550 // iterate from bottom to top over inner edge dofs
551 for (unsigned e = 0; e < numInnerEdgeDofs; ++e) {
552 subEntity[lastIndex++] = 4; // left edge (4)
553 for (unsigned i = 0; i < numInnerEdgeDofs; ++i)
554 subEntity[lastIndex++] = 4; // inner face dofs
555 subEntity[lastIndex++] = 5; // right edge (5)
556 }
557
558 // upper edge (7)
559 subEntity[lastIndex++] = 2; // corner 2
560 for (unsigned i = 0; i < k - 1; ++i)
561 subEntity[lastIndex++] = 7; // inner dofs of upper edge (7)
562 subEntity[lastIndex++] = 3; // corner 3
563
564 assert(numFaceIndices==lastIndex); // added 1 face so far
566
568 for(unsigned f = 0; f < numInnerEdgeDofs; ++f) {
569
570 // lower edge (connecting edges 0 and 1)
571 subEntity[lastIndex++] = 0; // dof on edge 0
572 for (unsigned i = 0; i < numInnerEdgeDofs; ++i)
573 subEntity[lastIndex++] = 2; // dof in front face
574 subEntity[lastIndex++] = 1; // dof on edge 1
575
576 // iterate from bottom to top over inner edge dofs
577 for (unsigned e = 0; e < numInnerEdgeDofs; ++e) {
578 subEntity[lastIndex++] = 0; // on left face (0)
579 for (unsigned i = 0; i < numInnerEdgeDofs; ++i)
580 subEntity[lastIndex++] = 0; // volume dofs
581 subEntity[lastIndex++] = 1; // right face (1)
582 }
583
584 // upper edge (connecting edges 0 and 1)
585 subEntity[lastIndex++] = 2; // dof on edge 2
586 for (unsigned i = 0; i < numInnerEdgeDofs; ++i)
587 subEntity[lastIndex++] = 3; // dof on rear face (3)
588 subEntity[lastIndex++] = 3; // dof on edge 3
589
590 assert(lastIndex==(f+1+1)*numFaceIndices);
591 }
592
594 // lower edge (10)
595 subEntity[lastIndex++] = 4; // corner 4
596 for (unsigned i = 0; i < k - 1; ++i)
597 subEntity[lastIndex++] = 10; // inner dofs on lower edge (10)
598 subEntity[lastIndex++] = 5; // corner 5
599
600 // iterate from bottom to top over inner edge dofs
601 for (unsigned e = 0; e < k - 1; ++e) {
602 subEntity[lastIndex++] = 8; // left edge (8)
603 for (unsigned i = 0; i < k - 1; ++i)
604 subEntity[lastIndex++] = 5; // face dofs
605 subEntity[lastIndex++] = 9; // right edge (9)
606 }
607
608 // upper edge (11)
609 subEntity[lastIndex++] = 6; // corner 6
610 for (unsigned i = 0; i < k - 1; ++i)
611 subEntity[lastIndex++] = 11; // inner dofs of upper edge (11)
612 subEntity[lastIndex++] = 7; // corner 7
613
614 assert(numIndices==lastIndex);
615 }
616
619 void setup ()
620 {
621 const unsigned int k = order();
622 localKeys_.resize(size());
623
624 if (k==0)
625 {
626 localKeys_[0] = LocalKey(0,0,0);
627 return;
628 }
629
630 if (k==1)
631 {
632 for (std::size_t i=0; i<size(); i++)
633 localKeys_[i] = LocalKey(i,dim,0);
634 return;
635 }
636
637 // Now: the general case
638
639 // Set up array of codimension-per-dof-number
641
642 for (std::size_t i=0; i<codim.size(); i++)
643 {
644 codim[i] = 0;
645
646 // Codimension gets increased by 1 for each coordinate direction
647 // where dof is on boundary
648 std::array<unsigned int,dim> mIdx = multiindex(i);
649 for (unsigned int j=0; j<dim; j++)
650 if (mIdx[j]==0 or mIdx[j]==k)
651 codim[i]++;
652 }
653
654 // Set up index vector (the index of the dof in the set of dofs of a given subentity)
655 // Algorithm: the 'index' has the same ordering as the dof number 'i'.
656 // To make it consecutive we interpret 'i' in the (k+1)-adic system, omit all digits
657 // that correspond to axes where the dof is on the element boundary, and transform the
658 // rest to the (k-1)-adic system.
660
661 for (std::size_t i=0; i<size(); i++)
662 {
663 index[i] = 0;
664
665 std::array<unsigned int,dim> mIdx = multiindex(i);
666
667 for (int j=dim-1; j>=0; j--)
668 if (mIdx[j]>0 && mIdx[j]<k)
669 index[i] = (k-1)*index[i] + (mIdx[j]-1);
670 }
671
672 // Set up entity and dof numbers for each (supported) dimension separately
673 std::vector<unsigned int> subEntity(size());
674
675 if (dim==1) {
676
677 setup1d(subEntity);
678
679 } else if (dim==2) {
680
681 setup2d(subEntity);
682
683 } else if (dim==3) {
684
685 setup3d(subEntity);
686
687 } else
688 DUNE_THROW(Dune::NotImplemented, "LagrangeCubeLocalCoefficients for order " << k << " and dim == " << dim);
689
690 for (size_t i=0; i<size(); i++)
691 localKeys_[i] = LocalKey(subEntity[i], codim[i], index[i]);
692 }
693
694 public:
696 explicit LagrangeCubeLocalCoefficients (OrderTraits orderTraits)
697 : OrderTraits(orderTraits)
698 {
699 setup();
700 }
701
702 using OrderTraits::size;
703 using OrderTraits::order;
704
706 constexpr const LocalKey& localKey (std::size_t i) const
707 {
708 return localKeys_[i];
709 }
710
711 private:
712 std::vector<LocalKey> localKeys_;
713 };
714
722 template<class D, class R, unsigned int dim, int compileTimeOrder>
723 class LagrangeCubeLocalInterpolation
724 : private LagrangeCubeOrderTraits<dim, compileTimeOrder>
725 {
726 using OrderTraits = LagrangeCubeOrderTraits<dim, compileTimeOrder>;
727 using Traits = typename LagrangeCubeLocalBasis<D,R,dim,compileTimeOrder>::Traits;
728
729 using OrderTraits::multiindex;
730 using OrderTraits::size;
731 using OrderTraits::order;
732
733 public:
735 explicit constexpr LagrangeCubeLocalInterpolation (OrderTraits orderTraits)
736 : OrderTraits(orderTraits)
737 {}
738
746 template<typename F, typename C>
747 constexpr void interpolate (const F& f, std::vector<C>& out) const
748 {
749 const unsigned int k = order();
750 out.resize(size());
751
752 // Specialization for zero-order case
753 if (k==0)
754 {
755 auto center = ReferenceElements<D,dim>::cube().position(0,0);
756 out[0] = Impl::rangeCast(f(center));
757 return;
758 }
759
760 typename Traits::DomainType x;
761
762 // Specialization for first-order case
763 if (k==1)
764 {
765 for (unsigned int i=0; i<size(); i++)
766 {
767 // Generate coordinate of the i-th corner of the reference cube
768 for (unsigned int j=0; j<dim; j++)
769 x[j] = (i & (1<<j)) ? 1.0 : 0.0;
770
771 out[i] = Impl::rangeCast(f(x));
772 }
773 return;
774 }
775
776 // The general case
777 for (unsigned int i=0; i<size(); i++)
778 {
779 // convert index i to multiindex
780 std::array<unsigned int,dim> alpha(multiindex(i));
781
782 // Generate coordinate of the i-th Lagrange point
783 for (unsigned int j=0; j<dim; j++)
784 x[j] = (1.0*alpha[j])/k;
785
786 out[i] = Impl::rangeCast(f(x));
787 }
788 }
789 };
790
791} } // namespace Dune::Impl
792
793namespace Dune
794{
803 template<class D, class R, int dim, int compileTimeOrder = -1>
805 : private Impl::LagrangeCubeOrderTraits<dim, compileTimeOrder>
806 {
807 using OrderTraits = Impl::LagrangeCubeOrderTraits<dim, compileTimeOrder>;
808
809 public:
813 Impl::LagrangeCubeLocalBasis<D,R,dim,compileTimeOrder>,
814 Impl::LagrangeCubeLocalCoefficients<dim,compileTimeOrder>,
815 Impl::LagrangeCubeLocalInterpolation<D,R,dim,compileTimeOrder> >;
816
819 : OrderTraits()
820 , basis_(*this)
821 , coefficients_(*this)
822 , interpolation_(*this)
823 {
824 static_assert(OrderTraits::is_static_order, "Default constructor only allowed for compile-time order >= 0");
825 static_assert(compileTimeOrder >= 0, "Default constructor only allowed for compile-time order >= 0");
826 }
827
829 explicit constexpr LagrangeCubeLocalFiniteElement (int runTimeOrder)
830 : OrderTraits(runTimeOrder)
831 , basis_(*this)
832 , coefficients_(*this)
833 , interpolation_(*this)
834 {
835 if (runTimeOrder < 0)
836 DUNE_THROW(Dune::InvalidStateException, "LagrangeCubeLocalFiniteElement: run-time order must be non-negative!");
837 if (compileTimeOrder >= 0 && compileTimeOrder != runTimeOrder)
838 DUNE_THROW(Dune::InvalidStateException, "LagrangeCubeLocalFiniteElement: Compile-time order must be identical to run-time order!");
839 }
840
843 constexpr const typename Traits::LocalBasisType& localBasis () const
844 {
845 return basis_;
846 }
847
850 constexpr const typename Traits::LocalCoefficientsType& localCoefficients () const
851 {
852 return coefficients_;
853 }
854
857 constexpr const typename Traits::LocalInterpolationType& localInterpolation () const
858 {
859 return interpolation_;
860 }
861
863 using OrderTraits::size;
864
867 static constexpr GeometryType type ()
868 {
869 return GeometryTypes::cube(dim);
870 }
871
872 private:
873 typename Traits::LocalBasisType basis_;
874 typename Traits::LocalCoefficientsType coefficients_;
875 typename Traits::LocalInterpolationType interpolation_;
876 };
877
878} // namespace Dune
879
880#endif // DUNE_LOCALFUNCTIONS_LAGRANGE_LAGRANGECUBE_HH
int size() const
iterator end()
iterator begin()
size_type dim() const
std::ptrdiff_t index() const
#define DUNE_THROW(E,...)
constexpr Base power(Base m, Exponent p)
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 cubes with arbitrary compile-time dimension and polynomial order.
Definition lagrangecube.hh:806
constexpr const Traits::LocalInterpolationType & localInterpolation() const
Returns object that evaluates degrees of freedom.
Definition lagrangecube.hh:857
constexpr LagrangeCubeLocalFiniteElement(int runTimeOrder)
Constructor for dynamic order.
Definition lagrangecube.hh:829
static constexpr GeometryType type()
The reference element that the local finite element is defined on.
Definition lagrangecube.hh:867
constexpr const Traits::LocalBasisType & localBasis() const
Returns the local basis, i.e., the set of shape functions.
Definition lagrangecube.hh:843
constexpr const Traits::LocalCoefficientsType & localCoefficients() const
Returns the assignment of the degrees of freedom to the element subentities.
Definition lagrangecube.hh:850
constexpr LagrangeCubeLocalFiniteElement()
Constructor for static order.
Definition lagrangecube.hh:818
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)