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/localkey.hh>
22namespace Dune {
namespace Impl
34 template<
class D,
class R,
unsigned int dim,
unsigned int k>
35 class LagrangeSimplexLocalBasis
38 using Traits = LocalBasisTraits<D,dim,FieldVector<D,dim>,R,1,FieldVector<R,1>,FieldMatrix<R,1,dim> >;
44 static constexpr unsigned int size ()
51 std::vector<typename Traits::RangeType>& out)
const
66 for (
size_t i=0; i<dim; i++)
76 auto lagrangeNode = [](
unsigned int i) {
return ((D)i)/k; };
80 for (
unsigned int i=0; i<
size(); i++)
83 for (
unsigned int alpha=0; alpha<i; alpha++)
84 out[i] *= (x[0]-lagrangeNode(alpha))/(lagrangeNode(i)-lagrangeNode(alpha));
85 for (
unsigned int gamma=i+1; gamma<=k; gamma++)
86 out[i] *= (x[0]-lagrangeNode(gamma))/(lagrangeNode(i)-lagrangeNode(gamma));
94 for (
unsigned int j=0; j<=k; j++)
95 for (
unsigned int i=0; i<=k-j; i++)
98 for (
unsigned int alpha=0; alpha<i; alpha++)
99 out[n] *= (x[0]-lagrangeNode(alpha))/(lagrangeNode(i)-lagrangeNode(alpha));
100 for (
unsigned int beta=0; beta<j; beta++)
101 out[n] *= (x[1]-lagrangeNode(beta))/(lagrangeNode(j)-lagrangeNode(beta));
102 for (
unsigned int gamma=i+j+1; gamma<=k; gamma++)
103 out[n] *= (lagrangeNode(gamma)-x[0]-x[1])/(lagrangeNode(gamma)-lagrangeNode(i)-lagrangeNode(j));
111 DUNE_THROW(NotImplemented,
"LagrangeSimplexLocalBasis for k>=2 only implemented for dim==1 or dim==3");
118 for (i[2] = 0; i[2] <= k; ++i[2])
121 for (
unsigned int j = 0; j < i[2]; ++j)
122 factor[2] *= (kx[2]-j) / (i[2]-j);
123 for (i[1] = 0; i[1] <= k - i[2]; ++i[1])
126 for (
unsigned int j = 0; j < i[1]; ++j)
127 factor[1] *= (kx[1]-j) / (i[1]-j);
128 for (i[0] = 0; i[0] <= k - i[1] - i[2]; ++i[0])
131 for (
unsigned int j = 0; j < i[0]; ++j)
132 factor[0] *= (kx[0]-j) / (i[0]-j);
133 i[3] = k - i[0] - i[1] - i[2];
134 D kx3 = k - kx[0] - kx[1] - kx[2];
136 for (
unsigned int j = 0; j < i[3]; ++j)
137 factor[3] *= (kx3-j) / (i[3]-j);
138 out[n++] = factor[0] * factor[1] * factor[2] * factor[3];
150 std::vector<typename Traits::JacobianType>& out)
const
157 std::fill(out[0][0].begin(), out[0][0].end(), 0);
164 std::fill(out[0][0].begin(), out[0][0].end(), -1);
166 for (
unsigned int i=0; i<dim; i++)
167 for (
unsigned int j=0; j<dim; j++)
168 out[i+1][0][j] = (i==j);
173 auto lagrangeNode = [](
unsigned int i) {
return ((D)i)/k; };
178 for (
unsigned int i=0; i<=k; i++)
183 for (
unsigned int a=0; a<i; a++)
186 for (
unsigned int alpha=0; alpha<i; alpha++)
187 product *= (alpha==a) ? 1.0/(lagrangeNode(i)-lagrangeNode(alpha))
188 : (x[0]-lagrangeNode(alpha))/(lagrangeNode(i)-lagrangeNode(alpha));
189 for (
unsigned int gamma=i+1; gamma<=k; gamma++)
190 product *= (lagrangeNode(gamma)-x[0])/(lagrangeNode(gamma)-lagrangeNode(i));
191 out[i][0][0] += product;
193 for (
unsigned int c=i+1; c<=k; c++)
196 for (
unsigned int alpha=0; alpha<i; alpha++)
197 product *= (x[0]-lagrangeNode(alpha))/(lagrangeNode(i)-lagrangeNode(alpha));
198 for (
unsigned int gamma=i+1; gamma<=k; gamma++)
199 product *= (gamma==c) ? -1.0/(lagrangeNode(gamma)-lagrangeNode(i))
200 : (lagrangeNode(gamma)-x[0])/(lagrangeNode(gamma)-lagrangeNode(i));
201 out[i][0][0] += product;
210 for (
unsigned int j=0; j<=k; j++)
211 for (
unsigned int i=0; i<=k-j; i++)
216 for (
unsigned int beta=0; beta<j; beta++)
217 factor *= (x[1]-lagrangeNode(beta))/(lagrangeNode(j)-lagrangeNode(beta));
218 for (
unsigned int a=0; a<i; a++)
221 for (
unsigned int alpha=0; alpha<i; alpha++)
223 product *= D(1)/(lagrangeNode(i)-lagrangeNode(alpha));
225 product *= (x[0]-lagrangeNode(alpha))/(lagrangeNode(i)-lagrangeNode(alpha));
226 for (
unsigned int gamma=i+j+1; gamma<=k; gamma++)
227 product *= (lagrangeNode(gamma)-x[0]-x[1])/(lagrangeNode(gamma)-lagrangeNode(i)-lagrangeNode(j));
228 out[n][0][0] += product;
230 for (
unsigned int c=i+j+1; c<=k; c++)
233 for (
unsigned int alpha=0; alpha<i; alpha++)
234 product *= (x[0]-lagrangeNode(alpha))/(lagrangeNode(i)-lagrangeNode(alpha));
235 for (
unsigned int gamma=i+j+1; gamma<=k; gamma++)
237 product *= -D(1)/(lagrangeNode(gamma)-lagrangeNode(i)-lagrangeNode(j));
239 product *= (lagrangeNode(gamma)-x[0]-x[1])/(lagrangeNode(gamma)-lagrangeNode(i)-lagrangeNode(j));
240 out[n][0][0] += product;
246 for (
unsigned int alpha=0; alpha<i; alpha++)
247 factor *= (x[0]-lagrangeNode(alpha))/(lagrangeNode(i)-lagrangeNode(alpha));
248 for (
unsigned int b=0; b<j; b++)
251 for (
unsigned int beta=0; beta<j; beta++)
253 product *= D(1)/(lagrangeNode(j)-lagrangeNode(beta));
255 product *= (x[1]-lagrangeNode(beta))/(lagrangeNode(j)-lagrangeNode(beta));
256 for (
unsigned int gamma=i+j+1; gamma<=k; gamma++)
257 product *= (lagrangeNode(gamma)-x[0]-x[1])/(lagrangeNode(gamma)-lagrangeNode(i)-lagrangeNode(j));
258 out[n][0][1] += product;
260 for (
unsigned int c=i+j+1; c<=k; c++)
263 for (
unsigned int beta=0; beta<j; beta++)
264 product *= (x[1]-lagrangeNode(beta))/(lagrangeNode(j)-lagrangeNode(beta));
265 for (
unsigned int gamma=i+j+1; gamma<=k; gamma++)
267 product *= -D(1)/(lagrangeNode(gamma)-lagrangeNode(i)-lagrangeNode(j));
269 product *= (lagrangeNode(gamma)-x[0]-x[1])/(lagrangeNode(gamma)-lagrangeNode(i)-lagrangeNode(j));
270 out[n][0][1] += product;
280 DUNE_THROW(NotImplemented,
"LagrangeSimplexLocalBasis only implemented for dim==3!");
288 for (i[2] = 0; i[2] <= k; ++i[2])
291 for (
unsigned int j = 0; j < i[2]; ++j)
292 factor[2] *= (kx[2]-j) / (i[2]-j);
293 for (i[1] = 0; i[1] <= k - i[2]; ++i[1])
296 for (
unsigned int j = 0; j < i[1]; ++j)
297 factor[1] *= (kx[1]-j) / (i[1]-j);
298 for (i[0] = 0; i[0] <= k - i[1] - i[2]; ++i[0])
301 for (
unsigned int j = 0; j < i[0]; ++j)
302 factor[0] *= (kx[0]-j) / (i[0]-j);
303 i[3] = k - i[0] - i[1] - i[2];
304 D kx3 = k - kx[0] - kx[1] - kx[2];
307 for (
unsigned int j = 0; j < i[3]; ++j)
308 factor[3] /= i[3] - j;
309 R prod_all = factor[0] * factor[1] * factor[2] * factor[3];
310 for (
unsigned int j = 0; j < i[3]; ++j)
313 for (
unsigned int l = 0; l < i[3]; ++l)
320 for (
unsigned int j = 0; j < i[3]; ++j)
321 factor[3] *= kx3 - j;
322 for (
unsigned int m = 0; m < 3; ++m)
325 for (
unsigned int j = 0; j < i[m]; ++j)
328 for (
unsigned int p = 0; p < 3; ++p)
331 for (
unsigned int l = 0; l < i[p]; ++l)
332 prod *= (j==l) ? R(k) / (i[p]-l) : R(kx[p]-l) / (i[p]-l);
336 out[n][0][m] += prod;
351 void partial(
const std::array<unsigned int,dim>& order,
353 std::vector<typename Traits::RangeType>& out)
const
359 if (totalOrder == 0) {
360 evaluateFunction(in, out);
374 auto direction = std::find(order.begin(), order.end(), 1);
377 for (
unsigned int i=0; i<dim; i++)
378 out[i+1] = (i==(direction-order.begin()));
381 std::fill(out.begin(), out.end(), 0);
387 auto lagrangeNode = [](
unsigned int i) {
return ((D)i)/k; };
390 auto lagrangianFactor = [&lagrangeNode]
395 return (x[0]-lagrangeNode(no))/(lagrangeNode(i)-lagrangeNode(no));
397 return (x[1]-lagrangeNode(no-i))/(lagrangeNode(j)-lagrangeNode(no-i));
398 return (lagrangeNode(no+1)-x[0]-x[1])/(lagrangeNode(no+1)-lagrangeNode(i)-lagrangeNode(j));
403 auto lagrangianFactorDerivative = [&lagrangeNode]
404 (
const int direction,
const int no,
const int i,
const int j,
const typename Traits::DomainType&)
409 return (direction == 0) ? T(1.0/(lagrangeNode(i)-lagrangeNode(no))) : T(0);
412 return (direction == 0) ? T(0) : T(1.0/(lagrangeNode(j)-lagrangeNode(no-i)));
414 return -1.0/(lagrangeNode(no+1)-lagrangeNode(i)-lagrangeNode(j));
419 int direction = std::find(order.begin(), order.end(), 1)-order.begin();
422 for (
unsigned int j=0; j<=k; j++)
424 for (
unsigned int i=0; i<=k-j; i++, n++)
427 for (
unsigned int no1=0; no1 < k; no1++)
429 R factor = lagrangianFactorDerivative(direction, no1, i, j, in);
430 for (
unsigned int no2=0; no2 < k; no2++)
432 factor *= lagrangianFactor(no2, i, j, in);
443 std::array<int,2> directions;
444 unsigned int counter = 0;
445 auto nonconstOrder = order;
446 for (
int i=0; i<2; i++)
448 while (nonconstOrder[i])
450 directions[counter++] = i;
457 for (
unsigned int j=0; j<=k; j++)
459 for (
unsigned int i=0; i<=k-j; i++, n++)
463 for (
unsigned int no1=0; no1 < k; no1++)
465 R factor1 = lagrangianFactorDerivative(directions[0], no1, i, j, in);
466 for (
unsigned int no2=0; no2 < k; no2++)
470 R factor2 = factor1*lagrangianFactorDerivative(directions[1], no2, i, j, in);
471 for (
unsigned int no3=0; no3 < k; no3++)
473 if (no3 == no1 || no3 == no2)
475 factor2 *= lagrangianFactor(no3, i, j, in);
489 DUNE_THROW(NotImplemented,
"Desired derivative order is not implemented");
493 static constexpr unsigned int order ()
504 template<
unsigned int dim,
unsigned int k>
505 class LagrangeSimplexLocalCoefficients
509 LagrangeSimplexLocalCoefficients ()
514 localKeys_[0] = LocalKey(0,0,0);
520 for (std::size_t i=0; i<
size(); i++)
521 localKeys_[i] = LocalKey(i,dim,0);
528 localKeys_[0] = LocalKey(0,1,0);
529 for (
unsigned int i=1; i<k; i++)
530 localKeys_[i] = LocalKey(0,0,i-1);
531 localKeys_.back() = LocalKey(1,1,0);
539 for (
unsigned int j=0; j<=k; j++)
540 for (
unsigned int i=0; i<=k-j; i++)
544 localKeys_[n++] = LocalKey(0,2,0);
549 localKeys_[n++] = LocalKey(1,2,0);
554 localKeys_[n++] = LocalKey(2,2,0);
559 localKeys_[n++] = LocalKey(0,1,i-1);
564 localKeys_[n++] = LocalKey(1,1,j-1);
569 localKeys_[n++] = LocalKey(2,1,j-1);
572 localKeys_[n++] = LocalKey(0,0,c++);
579 std::array<unsigned int, dim+1> vertexMap;
580 for (
unsigned int i=0; i<=dim; i++)
582 generateLocalKeys(vertexMap);
585 DUNE_THROW(NotImplemented,
"LagrangeSimplexLocalCoefficients only implemented for k<=1 or dim<=3!");
594 LagrangeSimplexLocalCoefficients (
const std::array<unsigned int, dim+1> vertexMap)
597 if (dim!=2 && dim!=3)
598 DUNE_THROW(NotImplemented,
"LagrangeSimplexLocalCoefficients only implemented for dim==2 and dim==3!");
600 generateLocalKeys(vertexMap);
604 template<
class VertexMap>
605 LagrangeSimplexLocalCoefficients(
const VertexMap &vertexmap)
608 if (dim!=2 && dim!=3)
609 DUNE_THROW(NotImplemented,
"LagrangeSimplexLocalCoefficients only implemented for dim==2 and dim==3!");
611 std::array<unsigned int, dim+1> vertexmap_array;
612 std::copy(vertexmap, vertexmap + dim + 1, vertexmap_array.begin());
613 generateLocalKeys(vertexmap_array);
617 static constexpr std::size_t
size ()
623 const LocalKey& localKey (std::size_t i)
const
625 return localKeys_[i];
629 std::vector<LocalKey> localKeys_;
631 void generateLocalKeys(
const std::array<unsigned int, dim+1> vertexMap)
635 localKeys_[0] = LocalKey(0,0,0);
644 for (
unsigned int j=0; j<=k; j++)
645 for (
unsigned int i=0; i<=k-j; i++)
649 localKeys_[n++] = LocalKey(0,2,0);
654 localKeys_[n++] = LocalKey(1,2,0);
659 localKeys_[n++] = LocalKey(2,2,0);
664 localKeys_[n++] = LocalKey(0,1,i-1);
669 localKeys_[n++] = LocalKey(1,1,j-1);
674 localKeys_[n++] = LocalKey(2,1,j-1);
677 localKeys_[n++] = LocalKey(0,0,c++);
682 flip[0] = vertexMap[0] > vertexMap[1];
683 flip[1] = vertexMap[0] > vertexMap[2];
684 flip[2] = vertexMap[1] > vertexMap[2];
685 for (std::size_t i=0; i<
size(); i++)
686 if (localKeys_[i].codim()==1 && flip[localKeys_[i].subEntity()])
687 localKeys_[i].index(k-2-localKeys_[i].index());
693 DUNE_THROW(NotImplemented,
"LagrangeSimplexLocalCoefficients only implemented for dim==3!");
695 unsigned int subindex[16];
696 unsigned int codim_count[4] = {0};
697 for (
unsigned int m = 1; m < 16; ++m)
699 unsigned int codim = !(m&1) + !(m&2) + !(m&4) + !(m&8);
700 subindex[m] = codim_count[codim]++;
703 int a1 = (3*k + 12)*k + 11;
705 unsigned int dof_count[16] = {0};
707 for (i[3] = 0; i[3] <= k; ++i[3])
708 for (i[2] = 0; i[2] <= k - i[3]; ++i[2])
709 for (i[1] = 0; i[1] <= k - i[2] - i[3]; ++i[1])
711 i[0] = k - i[1] - i[2] - i[3];
713 unsigned int entity = 0;
714 unsigned int codim = 0;
715 for (
unsigned int m = 0; m < 4; ++m)
717 j[m] = i[vertexMap[m]];
718 entity += !!j[m] << m;
721 int local_index = j[3]*(a1 + (a2 + j[3])*j[3])/6
722 + j[2]*(2*(k - j[3]) + 3 - j[2])/2 + j[1];
723 localKeys_[local_index] = LocalKey(subindex[entity], codim, dof_count[entity]++);
732 template<
class LocalBasis>
733 class LagrangeSimplexLocalInterpolation
735 static const int kdiv = (LocalBasis::order() == 0 ? 1 : LocalBasis::order());
745 template<
typename F,
typename C>
746 void interpolate (
const F& f, std::vector<C>& out)
const
748 constexpr auto dim = LocalBasis::Traits::dimDomain;
749 constexpr auto k = LocalBasis::order();
750 using D =
typename LocalBasis::Traits::DomainFieldType;
752 typename LocalBasis::Traits::DomainType x;
754 out.resize(LocalBasis::size());
768 std::fill(x.begin(), x.end(), 0);
772 for (
int i=0; i<dim; i++)
774 for (
int j=0; j<dim; j++)
784 for (
unsigned int i=0; i<k+1; i++)
795 for (
unsigned int j=0; j<=k; j++)
796 for (
unsigned int i=0; i<=k-j; i++)
798 x = { ((D)i)/k, ((D)j)/k };
806 DUNE_THROW(NotImplemented,
"LagrangeSimplexLocalInterpolation only implemented for dim<=3!");
809 for (
int i2 = 0; i2 <= (int)k; i2++)
810 for (
int i1 = 0; i1 <= (int)k-i2; i1++)
811 for (
int i0 = 0; i0 <= (int)k-i1-i2; i0++)
813 x[0] = ((D)i0)/((D)kdiv);
814 x[1] = ((D)i1)/((D)kdiv);
815 x[2] = ((D)i2)/((D)kdiv);
834 template<
class D,
class R,
int d,
int k>
841 Impl::LagrangeSimplexLocalCoefficients<d,k>,
842 Impl::LagrangeSimplexLocalInterpolation<Impl::LagrangeSimplexLocalBasis<D,R,d,k> > >;
851 template<
typename VertexMap>
853 : coefficients_(vertexmap)
867 return coefficients_;
874 return interpolation_;
878 static constexpr std::size_t
size ()
880 return Impl::LagrangeSimplexLocalBasis<D,R,d,k>::size();
891 Impl::LagrangeSimplexLocalBasis<D,R,d,k> basis_;
892 Impl::LagrangeSimplexLocalCoefficients<d,k> coefficients_;
893 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:114
Lagrange finite element for simplices with arbitrary compile-time dimension and polynomial order.
Definition: lagrangesimplex.hh:836
const Traits::LocalInterpolationType & localInterpolation() const
Returns object that evaluates degrees of freedom.
Definition: lagrangesimplex.hh:872
const Traits::LocalBasisType & localBasis() const
Returns the local basis, i.e., the set of shape functions.
Definition: lagrangesimplex.hh:858
LagrangeSimplexLocalFiniteElement()
Definition: lagrangesimplex.hh:845
static constexpr std::size_t size()
The number of shape functions.
Definition: lagrangesimplex.hh:878
LagrangeSimplexLocalFiniteElement(const VertexMap &vertexmap)
Definition: lagrangesimplex.hh:852
const Traits::LocalCoefficientsType & localCoefficients() const
Returns the assignment of the degrees of freedom to the element subentities.
Definition: lagrangesimplex.hh:865
static constexpr GeometryType type()
The reference element that the local finite element is defined on.
Definition: lagrangesimplex.hh:885
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:453
constexpr T accumulate(Range &&range, T value, F &&f)
Accumulate values.
Definition: hybridutilities.hh:279
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:131
static const ReferenceElement & simplex()
get simplex reference elements
Definition: referenceelements.hh:162
D DomainType
domain type
Definition: localbasis.hh:43
R RangeType
range type
Definition: localbasis.hh:52
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