5#ifndef DUNE_LOCALFUNCTIONS_LAGRANGE_LAGRANGESIMPLEX_HH
6#define DUNE_LOCALFUNCTIONS_LAGRANGE_LAGRANGESIMPLEX_HH
16#include <dune/geometry/referenceelements.hh>
18#include <dune/localfunctions/common/localbasis.hh>
19#include <dune/localfunctions/common/localfiniteelementtraits.hh>
20#include <dune/localfunctions/common/localinterpolation.hh>
21#include <dune/localfunctions/common/localkey.hh>
23namespace Dune {
namespace Impl
35 template<
class D,
class R,
unsigned int dim,
unsigned int k>
36 class LagrangeSimplexLocalBasis
39 using Traits = LocalBasisTraits<D,dim,FieldVector<D,dim>,R,1,FieldVector<R,1>,FieldMatrix<R,1,dim> >;
45 static constexpr unsigned int size ()
52 std::vector<typename Traits::RangeType>& out)
const
67 for (
size_t i=0; i<dim; i++)
77 auto lagrangeNode = [](
unsigned int i) {
return ((D)i)/k; };
81 for (
unsigned int i=0; i<size(); i++)
84 for (
unsigned int alpha=0; alpha<i; alpha++)
85 out[i] *= (x[0]-lagrangeNode(alpha))/(lagrangeNode(i)-lagrangeNode(alpha));
86 for (
unsigned int gamma=i+1; gamma<=k; gamma++)
87 out[i] *= (x[0]-lagrangeNode(gamma))/(lagrangeNode(i)-lagrangeNode(gamma));
95 for (
unsigned int j=0; j<=k; j++)
96 for (
unsigned int i=0; i<=k-j; i++)
99 for (
unsigned int alpha=0; alpha<i; alpha++)
100 out[n] *= (x[0]-lagrangeNode(alpha))/(lagrangeNode(i)-lagrangeNode(alpha));
101 for (
unsigned int beta=0; beta<j; beta++)
102 out[n] *= (x[1]-lagrangeNode(beta))/(lagrangeNode(j)-lagrangeNode(beta));
103 for (
unsigned int gamma=i+j+1; gamma<=k; gamma++)
104 out[n] *= (lagrangeNode(gamma)-x[0]-x[1])/(lagrangeNode(gamma)-lagrangeNode(i)-lagrangeNode(j));
112 DUNE_THROW(NotImplemented,
"LagrangeSimplexLocalBasis for k>=2 only implemented for dim==1 or dim==3");
119 for (i[2] = 0; i[2] <= k; ++i[2])
122 for (
unsigned int j = 0; j < i[2]; ++j)
123 factor[2] *= (kx[2]-j) / (i[2]-j);
124 for (i[1] = 0; i[1] <= k - i[2]; ++i[1])
127 for (
unsigned int j = 0; j < i[1]; ++j)
128 factor[1] *= (kx[1]-j) / (i[1]-j);
129 for (i[0] = 0; i[0] <= k - i[1] - i[2]; ++i[0])
132 for (
unsigned int j = 0; j < i[0]; ++j)
133 factor[0] *= (kx[0]-j) / (i[0]-j);
134 i[3] = k - i[0] - i[1] - i[2];
135 D kx3 = k - kx[0] - kx[1] - kx[2];
137 for (
unsigned int j = 0; j < i[3]; ++j)
138 factor[3] *= (kx3-j) / (i[3]-j);
139 out[n++] = factor[0] * factor[1] * factor[2] * factor[3];
151 std::vector<typename Traits::JacobianType>& out)
const
158 std::fill(out[0][0].begin(), out[0][0].end(), 0);
165 std::fill(out[0][0].begin(), out[0][0].end(), -1);
167 for (
unsigned int i=0; i<dim; i++)
168 for (
unsigned int j=0; j<dim; j++)
169 out[i+1][0][j] = (i==j);
174 auto lagrangeNode = [](
unsigned int i) {
return ((D)i)/k; };
179 for (
unsigned int i=0; i<=k; i++)
184 for (
unsigned int a=0; a<i; a++)
187 for (
unsigned int alpha=0; alpha<i; alpha++)
188 product *= (alpha==a) ? 1.0/(lagrangeNode(i)-lagrangeNode(alpha))
189 : (x[0]-lagrangeNode(alpha))/(lagrangeNode(i)-lagrangeNode(alpha));
190 for (
unsigned int gamma=i+1; gamma<=k; gamma++)
191 product *= (lagrangeNode(gamma)-x[0])/(lagrangeNode(gamma)-lagrangeNode(i));
192 out[i][0][0] += product;
194 for (
unsigned int c=i+1; c<=k; c++)
197 for (
unsigned int alpha=0; alpha<i; alpha++)
198 product *= (x[0]-lagrangeNode(alpha))/(lagrangeNode(i)-lagrangeNode(alpha));
199 for (
unsigned int gamma=i+1; gamma<=k; gamma++)
200 product *= (gamma==c) ? -1.0/(lagrangeNode(gamma)-lagrangeNode(i))
201 : (lagrangeNode(gamma)-x[0])/(lagrangeNode(gamma)-lagrangeNode(i));
202 out[i][0][0] += product;
211 for (
unsigned int j=0; j<=k; j++)
212 for (
unsigned int i=0; i<=k-j; i++)
217 for (
unsigned int beta=0; beta<j; beta++)
218 factor *= (x[1]-lagrangeNode(beta))/(lagrangeNode(j)-lagrangeNode(beta));
219 for (
unsigned int a=0; a<i; a++)
222 for (
unsigned int alpha=0; alpha<i; alpha++)
224 product *= D(1)/(lagrangeNode(i)-lagrangeNode(alpha));
226 product *= (x[0]-lagrangeNode(alpha))/(lagrangeNode(i)-lagrangeNode(alpha));
227 for (
unsigned int gamma=i+j+1; gamma<=k; gamma++)
228 product *= (lagrangeNode(gamma)-x[0]-x[1])/(lagrangeNode(gamma)-lagrangeNode(i)-lagrangeNode(j));
229 out[n][0][0] += product;
231 for (
unsigned int c=i+j+1; c<=k; c++)
234 for (
unsigned int alpha=0; alpha<i; alpha++)
235 product *= (x[0]-lagrangeNode(alpha))/(lagrangeNode(i)-lagrangeNode(alpha));
236 for (
unsigned int gamma=i+j+1; gamma<=k; gamma++)
238 product *= -D(1)/(lagrangeNode(gamma)-lagrangeNode(i)-lagrangeNode(j));
240 product *= (lagrangeNode(gamma)-x[0]-x[1])/(lagrangeNode(gamma)-lagrangeNode(i)-lagrangeNode(j));
241 out[n][0][0] += product;
247 for (
unsigned int alpha=0; alpha<i; alpha++)
248 factor *= (x[0]-lagrangeNode(alpha))/(lagrangeNode(i)-lagrangeNode(alpha));
249 for (
unsigned int b=0; b<j; b++)
252 for (
unsigned int beta=0; beta<j; beta++)
254 product *= D(1)/(lagrangeNode(j)-lagrangeNode(beta));
256 product *= (x[1]-lagrangeNode(beta))/(lagrangeNode(j)-lagrangeNode(beta));
257 for (
unsigned int gamma=i+j+1; gamma<=k; gamma++)
258 product *= (lagrangeNode(gamma)-x[0]-x[1])/(lagrangeNode(gamma)-lagrangeNode(i)-lagrangeNode(j));
259 out[n][0][1] += product;
261 for (
unsigned int c=i+j+1; c<=k; c++)
264 for (
unsigned int beta=0; beta<j; beta++)
265 product *= (x[1]-lagrangeNode(beta))/(lagrangeNode(j)-lagrangeNode(beta));
266 for (
unsigned int gamma=i+j+1; gamma<=k; gamma++)
268 product *= -D(1)/(lagrangeNode(gamma)-lagrangeNode(i)-lagrangeNode(j));
270 product *= (lagrangeNode(gamma)-x[0]-x[1])/(lagrangeNode(gamma)-lagrangeNode(i)-lagrangeNode(j));
271 out[n][0][1] += product;
281 DUNE_THROW(NotImplemented,
"LagrangeSimplexLocalBasis only implemented for dim==3!");
289 for (i[2] = 0; i[2] <= k; ++i[2])
292 for (
unsigned int j = 0; j < i[2]; ++j)
293 factor[2] *= (kx[2]-j) / (i[2]-j);
294 for (i[1] = 0; i[1] <= k - i[2]; ++i[1])
297 for (
unsigned int j = 0; j < i[1]; ++j)
298 factor[1] *= (kx[1]-j) / (i[1]-j);
299 for (i[0] = 0; i[0] <= k - i[1] - i[2]; ++i[0])
302 for (
unsigned int j = 0; j < i[0]; ++j)
303 factor[0] *= (kx[0]-j) / (i[0]-j);
304 i[3] = k - i[0] - i[1] - i[2];
305 D kx3 = k - kx[0] - kx[1] - kx[2];
308 for (
unsigned int j = 0; j < i[3]; ++j)
309 factor[3] /= i[3] - j;
310 R prod_all = factor[0] * factor[1] * factor[2] * factor[3];
311 for (
unsigned int j = 0; j < i[3]; ++j)
314 for (
unsigned int l = 0; l < i[3]; ++l)
321 for (
unsigned int j = 0; j < i[3]; ++j)
322 factor[3] *= kx3 - j;
323 for (
unsigned int m = 0; m < 3; ++m)
326 for (
unsigned int j = 0; j < i[m]; ++j)
329 for (
unsigned int p = 0; p < 3; ++p)
332 for (
unsigned int l = 0; l < i[p]; ++l)
333 prod *= (j==l) ? R(k) / (i[p]-l) : (kx[p]-l) / (i[p]-l);
337 out[n][0][m] += prod;
352 void partial(
const std::array<unsigned int,dim>& order,
354 std::vector<typename Traits::RangeType>& out)
const
360 if (totalOrder == 0) {
361 evaluateFunction(in, out);
375 auto direction = std::find(order.begin(), order.end(), 1);
378 for (
unsigned int i=0; i<dim; i++)
379 out[i+1] = (i==(direction-order.begin()));
382 std::fill(out.begin(), out.end(), 0);
388 auto lagrangeNode = [](
unsigned int i) {
return ((D)i)/k; };
391 auto lagrangianFactor = [&lagrangeNode]
396 return (x[0]-lagrangeNode(no))/(lagrangeNode(i)-lagrangeNode(no));
398 return (x[1]-lagrangeNode(no-i))/(lagrangeNode(j)-lagrangeNode(no-i));
399 return (lagrangeNode(no+1)-x[0]-x[1])/(lagrangeNode(no+1)-lagrangeNode(i)-lagrangeNode(j));
404 auto lagrangianFactorDerivative = [&lagrangeNode]
405 (
const int direction,
const int no,
const int i,
const int j,
const typename Traits::DomainType&)
410 return (direction == 0) ? T(1.0/(lagrangeNode(i)-lagrangeNode(no))) : T(0);
413 return (direction == 0) ? T(0) : T(1.0/(lagrangeNode(j)-lagrangeNode(no-i)));
415 return -1.0/(lagrangeNode(no+1)-lagrangeNode(i)-lagrangeNode(j));
420 int direction = std::find(order.begin(), order.end(), 1)-order.begin();
423 for (
unsigned int j=0; j<=k; j++)
425 for (
unsigned int i=0; i<=k-j; i++, n++)
428 for (
unsigned int no1=0; no1 < k; no1++)
430 R factor = lagrangianFactorDerivative(direction, no1, i, j, in);
431 for (
unsigned int no2=0; no2 < k; no2++)
433 factor *= lagrangianFactor(no2, i, j, in);
444 std::array<int,2> directions;
445 unsigned int counter = 0;
446 auto nonconstOrder = order;
447 for (
int i=0; i<2; i++)
449 while (nonconstOrder[i])
451 directions[counter++] = i;
458 for (
unsigned int j=0; j<=k; j++)
460 for (
unsigned int i=0; i<=k-j; i++, n++)
464 for (
unsigned int no1=0; no1 < k; no1++)
466 R factor1 = lagrangianFactorDerivative(directions[0], no1, i, j, in);
467 for (
unsigned int no2=0; no2 < k; no2++)
471 R factor2 = factor1*lagrangianFactorDerivative(directions[1], no2, i, j, in);
472 for (
unsigned int no3=0; no3 < k; no3++)
474 if (no3 == no1 || no3 == no2)
476 factor2 *= lagrangianFactor(no3, i, j, in);
490 DUNE_THROW(NotImplemented,
"Desired derivative order is not implemented");
494 static constexpr unsigned int order ()
505 template<
unsigned int dim,
unsigned int k>
506 class LagrangeSimplexLocalCoefficients
510 LagrangeSimplexLocalCoefficients ()
515 localKeys_[0] = LocalKey(0,0,0);
521 for (std::size_t i=0; i<size(); i++)
522 localKeys_[i] = LocalKey(i,dim,0);
529 localKeys_[0] = LocalKey(0,1,0);
530 for (
unsigned int i=1; i<k; i++)
531 localKeys_[i] = LocalKey(0,0,i-1);
532 localKeys_.back() = LocalKey(1,1,0);
540 for (
unsigned int j=0; j<=k; j++)
541 for (
unsigned int i=0; i<=k-j; i++)
545 localKeys_[n++] = LocalKey(0,2,0);
550 localKeys_[n++] = LocalKey(1,2,0);
555 localKeys_[n++] = LocalKey(2,2,0);
560 localKeys_[n++] = LocalKey(0,1,i-1);
565 localKeys_[n++] = LocalKey(1,1,j-1);
570 localKeys_[n++] = LocalKey(2,1,j-1);
573 localKeys_[n++] = LocalKey(0,0,c++);
580 std::array<unsigned int, dim+1> vertexMap;
581 for (
unsigned int i=0; i<=dim; i++)
583 generateLocalKeys(vertexMap);
586 DUNE_THROW(NotImplemented,
"LagrangeSimplexLocalCoefficients only implemented for k<=1 or dim<=3!");
595 LagrangeSimplexLocalCoefficients (
const std::array<unsigned int, dim+1> vertexMap)
598 if (dim!=2 && dim!=3)
599 DUNE_THROW(NotImplemented,
"LagrangeSimplexLocalCoefficients only implemented for dim==2 and dim==3!");
601 generateLocalKeys(vertexMap);
605 template<
class VertexMap>
606 LagrangeSimplexLocalCoefficients(
const VertexMap &vertexmap)
609 if (dim!=2 && dim!=3)
610 DUNE_THROW(NotImplemented,
"LagrangeSimplexLocalCoefficients only implemented for dim==2 and dim==3!");
612 std::array<unsigned int, dim+1> vertexmap_array;
613 std::copy(vertexmap, vertexmap + dim + 1, vertexmap_array.begin());
614 generateLocalKeys(vertexmap_array);
618 static constexpr std::size_t size ()
624 const LocalKey& localKey (std::size_t i)
const
626 return localKeys_[i];
630 std::vector<LocalKey> localKeys_;
632 void generateLocalKeys(
const std::array<unsigned int, dim+1> vertexMap)
636 localKeys_[0] = LocalKey(0,0,0);
645 for (
unsigned int j=0; j<=k; j++)
646 for (
unsigned int i=0; i<=k-j; i++)
650 localKeys_[n++] = LocalKey(0,2,0);
655 localKeys_[n++] = LocalKey(1,2,0);
660 localKeys_[n++] = LocalKey(2,2,0);
665 localKeys_[n++] = LocalKey(0,1,i-1);
670 localKeys_[n++] = LocalKey(1,1,j-1);
675 localKeys_[n++] = LocalKey(2,1,j-1);
678 localKeys_[n++] = LocalKey(0,0,c++);
683 flip[0] = vertexMap[0] > vertexMap[1];
684 flip[1] = vertexMap[0] > vertexMap[2];
685 flip[2] = vertexMap[1] > vertexMap[2];
686 for (std::size_t i=0; i<size(); i++)
687 if (localKeys_[i].codim()==1 && flip[localKeys_[i].subEntity()])
688 localKeys_[i].index(k-2-localKeys_[i].index());
694 DUNE_THROW(NotImplemented,
"LagrangeSimplexLocalCoefficients only implemented for dim==3!");
696 unsigned int subindex[16];
697 unsigned int codim_count[4] = {0};
698 for (
unsigned int m = 1; m < 16; ++m)
700 unsigned int codim = !(m&1) + !(m&2) + !(m&4) + !(m&8);
701 subindex[m] = codim_count[codim]++;
704 int a1 = (3*k + 12)*k + 11;
706 unsigned int dof_count[16] = {0};
708 for (i[3] = 0; i[3] <= k; ++i[3])
709 for (i[2] = 0; i[2] <= k - i[3]; ++i[2])
710 for (i[1] = 0; i[1] <= k - i[2] - i[3]; ++i[1])
712 i[0] = k - i[1] - i[2] - i[3];
714 unsigned int entity = 0;
715 unsigned int codim = 0;
716 for (
unsigned int m = 0; m < 4; ++m)
718 j[m] = i[vertexMap[m]];
719 entity += !!j[m] << m;
722 int local_index = j[3]*(a1 + (a2 + j[3])*j[3])/6
723 + j[2]*(2*(k - j[3]) + 3 - j[2])/2 + j[1];
724 localKeys_[local_index] = LocalKey(subindex[entity], codim, dof_count[entity]++);
733 template<
class LocalBasis>
734 class LagrangeSimplexLocalInterpolation
736 static const int kdiv = (LocalBasis::order() == 0 ? 1 : LocalBasis::order());
746 template<
typename F,
typename C>
747 void interpolate (
const F& ff, std::vector<C>& out)
const
749 constexpr auto dim = LocalBasis::Traits::dimDomain;
750 constexpr auto k = LocalBasis::order();
751 using D =
typename LocalBasis::Traits::DomainFieldType;
753 typename LocalBasis::Traits::DomainType x;
754 auto&& f = Impl::makeFunctionWithCallOperator<typename LocalBasis::Traits::DomainType>(ff);
756 out.resize(LocalBasis::size());
770 std::fill(x.begin(), x.end(), 0);
774 for (
int i=0; i<dim; i++)
776 for (
int j=0; j<dim; j++)
786 for (
unsigned int i=0; i<k+1; i++)
797 for (
unsigned int j=0; j<=k; j++)
798 for (
unsigned int i=0; i<=k-j; i++)
800 x = { ((D)i)/k, ((D)j)/k };
808 DUNE_THROW(NotImplemented,
"LagrangeSimplexLocalInterpolation only implemented for dim<=3!");
811 for (
int i2 = 0; i2 <= (int)k; i2++)
812 for (
int i1 = 0; i1 <= (int)k-i2; i1++)
813 for (
int i0 = 0; i0 <= (int)k-i1-i2; i0++)
815 x[0] = ((D)i0)/((D)kdiv);
816 x[1] = ((D)i1)/((D)kdiv);
817 x[2] = ((D)i2)/((D)kdiv);
836 template<
class D,
class R,
int d,
int k>
843 Impl::LagrangeSimplexLocalCoefficients<d,k>,
844 Impl::LagrangeSimplexLocalInterpolation<Impl::LagrangeSimplexLocalBasis<D,R,d,k> > >;
853 template<
typename VertexMap>
855 : coefficients_(vertexmap)
869 return coefficients_;
876 return interpolation_;
880 static constexpr std::size_t
size ()
882 return Impl::LagrangeSimplexLocalBasis<D,R,d,k>::size();
893 Impl::LagrangeSimplexLocalBasis<D,R,d,k> basis_;
894 Impl::LagrangeSimplexLocalCoefficients<d,k> coefficients_;
895 Impl::LagrangeSimplexLocalInterpolation<Impl::LagrangeSimplexLocalBasis<D,R,d,k> > interpolation_;
Unique label for each type of entities that can occur in DUNE grids.
Definition: type.hh:125
Lagrange finite element for simplices with arbitrary compile-time dimension and polynomial order.
Definition: lagrangesimplex.hh:838
const Traits::LocalInterpolationType & localInterpolation() const
Returns object that evaluates degrees of freedom.
Definition: lagrangesimplex.hh:874
const Traits::LocalBasisType & localBasis() const
Returns the local basis, i.e., the set of shape functions.
Definition: lagrangesimplex.hh:860
LagrangeSimplexLocalFiniteElement()
Definition: lagrangesimplex.hh:847
static constexpr std::size_t size()
The number of shape functions.
Definition: lagrangesimplex.hh:880
LagrangeSimplexLocalFiniteElement(const VertexMap &vertexmap)
Definition: lagrangesimplex.hh:854
const Traits::LocalCoefficientsType & localCoefficients() const
Returns the assignment of the degrees of freedom to the element subentities.
Definition: lagrangesimplex.hh:867
static constexpr GeometryType type()
The reference element that the local finite element is defined on.
Definition: lagrangesimplex.hh:887
Definition of the DUNE_NO_DEPRECATED_* macros.
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, m)
Definition: exceptions.hh:218
constexpr GeometryType simplex(unsigned int dim)
Returns a GeometryType representing a simplex of dimension dim.
Definition: type.hh:463
constexpr T accumulate(Range &&range, T value, F &&f)
Accumulate values.
Definition: hybridutilities.hh:291
Some useful basic math stuff.
Dune namespace.
Definition: alignedallocator.hh:13
static constexpr T binomial(const T &n, const T &k) noexcept
calculate the binomial coefficient n over k as a constexpr
Definition: math.hh:131
static const ReferenceElement & simplex()
get simplex reference elements
Definition: referenceelements.hh:204
D DomainType
domain type
Definition: localbasis.hh:42
R RangeType
range type
Definition: localbasis.hh:51
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