3#ifndef DUNE_LOCALFUNCTIONS_LAGRANGE_LAGRANGECUBE_HH
4#define DUNE_LOCALFUNCTIONS_LAGRANGE_LAGRANGECUBE_HH
13#include <dune/geometry/referenceelements.hh>
15#include <dune/localfunctions/common/localbasis.hh>
16#include <dune/localfunctions/common/localfiniteelementtraits.hh>
17#include <dune/localfunctions/common/localinterpolation.hh>
18#include <dune/localfunctions/common/localkey.hh>
20namespace Dune {
namespace Impl
23 template<
class LocalBasis>
24 class LagrangeCubeLocalInterpolation;
36 template<
class D,
class R,
unsigned int dim,
unsigned int k>
37 class LagrangeCubeLocalBasis
39 friend class LagrangeCubeLocalInterpolation<LagrangeCubeLocalBasis<D,R,dim,k> >;
42 static R p(
unsigned int i, D x)
45 for (
unsigned int j=0; j<=k; j++)
46 if (j!=i) result *= (k*x-j)/((
int)i-(int)j);
51 static R dp(
unsigned int i, D x)
55 for (
unsigned int j=0; j<=k; j++)
59 R prod( (k*1.0)/((
int)i-(
int)j) );
60 for (
unsigned int l=0; l<=k; l++)
62 prod *= (k*x-l)/((
int)i-(int)l);
71 static R ddp(
unsigned int j, D x)
75 for (
unsigned int i=0; i<=k; i++)
82 for (
unsigned int m=0; m<=k; m++)
87 R prod( (k*1.0)/((
int)j-(
int)m) );
88 for (
unsigned int l=0; l<=k; l++)
89 if (l!=i && l!=j && l!=m)
90 prod *= (k*x-l)/((
int)j-(int)l);
94 result += sum * ( (k*1.0)/((
int)j-(int)i) );
101 static std::array<unsigned int,dim> multiindex (
unsigned int i)
103 std::array<unsigned int,dim> alpha;
104 for (
unsigned int j=0; j<dim; j++)
106 alpha[j] = i % (k+1);
113 using Traits = LocalBasisTraits<D,dim,FieldVector<D,dim>,R,1,FieldVector<R,1>,FieldMatrix<R,1,dim> >;
117 static constexpr unsigned int size ()
119 return power(k+1, dim);
124 std::vector<typename Traits::RangeType>& out)
const
137 for (
size_t i=0; i<size(); i++)
141 for (
unsigned int j=0; j<dim; j++)
143 out[i] *= (i & (1<<j)) ? x[j] : 1-x[j];
149 for (
size_t i=0; i<size(); i++)
152 std::array<unsigned int,dim> alpha(multiindex(i));
158 for (
unsigned int j=0; j<dim; j++)
159 out[i] *= p(alpha[j],x[j]);
169 std::vector<typename Traits::JacobianType>& out)
const
176 std::fill(out[0][0].begin(), out[0][0].end(), 0);
184 for (
size_t i=0; i<size(); i++)
187 for (
unsigned int j=0; j<dim; j++)
191 out[i][0][j] = (i & (1<<j)) ? 1 : -1;
193 for (
unsigned int l=0; l<dim; l++)
197 out[i][0][j] *= (i & (1<<l)) ? x[l] : 1-x[l];
207 for (
size_t i=0; i<size(); i++)
210 std::array<unsigned int,dim> alpha(multiindex(i));
213 for (
unsigned int j=0; j<dim; j++)
217 out[i][0][j] = dp(alpha[j],x[j]);
220 for (
unsigned int l=0; l<dim; l++)
222 out[i][0][j] *= p(alpha[l],x[l]);
233 void partial(
const std::array<unsigned int,dim>& order,
235 std::vector<typename Traits::RangeType>& out)
const
243 out[0] = (totalOrder==0);
251 evaluateFunction(in, out);
253 else if (totalOrder == 1)
257 auto direction = std::distance(order.begin(), std::find(order.begin(), order.end(), 1));
258 if (direction >= dim)
259 DUNE_THROW(RangeError,
"Direction of partial derivative not found!");
262 for (std::size_t i = 0; i < size(); ++i)
266 out[i] = (i & (1<<direction)) ? 1 : -1;
268 for (
unsigned int j = 0; j < dim; ++j)
272 out[i] *= (i & (1<<j)) ? in[j] : 1-in[j];
276 else if (totalOrder == 2)
279 for (
size_t i=0; i<size(); i++)
282 std::array<unsigned int,dim> alpha(multiindex(i));
288 for (std::size_t l=0; l<dim; l++)
293 out[i][0] *= p(alpha[l],in[l]);
297 out[i][0] *= dp(alpha[l],in[l]);
303 DUNE_THROW(NotImplemented,
"Desired derivative order is not implemented");
309 DUNE_THROW(NotImplemented,
"Partial derivative of order " << totalOrder <<
" is not implemented!");
317 for (
size_t i=0; i<size(); i++)
320 std::array<unsigned int,dim> alpha(multiindex(i));
326 for (std::size_t l=0; l<dim; l++)
331 out[i][0] *= p(alpha[l],in[l]);
334 out[i][0] *= dp(alpha[l],in[l]);
337 out[i][0] *= ddp(alpha[l],in[l]);
340 DUNE_THROW(NotImplemented,
"Desired derivative order is not implemented");
347 static constexpr unsigned int order ()
358 template<
unsigned int dim,
unsigned int k>
359 class LagrangeCubeLocalCoefficients
362 static std::array<unsigned int,dim> multiindex (
unsigned int i)
364 std::array<unsigned int,dim> alpha;
365 for (
unsigned int j=0; j<dim; j++)
367 alpha[j] = i % (k+1);
374 void setup1d(std::vector<unsigned int>& subEntity)
378 unsigned lastIndex=0;
385 subEntity[lastIndex++] = 0;
386 for (
unsigned i = 0; i < k - 1; ++i)
387 subEntity[lastIndex++] = 0;
389 subEntity[lastIndex++] = 1;
391 assert(
power(k+1,dim)==lastIndex);
394 void setup2d(std::vector<unsigned int>& subEntity)
398 unsigned lastIndex=0;
412 subEntity[lastIndex++] = 0;
413 for (
unsigned i = 0; i < k - 1; ++i)
414 subEntity[lastIndex++] = 2;
416 subEntity[lastIndex++] = 1;
419 for (
unsigned e = 0; e < k - 1; ++e) {
420 subEntity[lastIndex++] = 0;
421 for (
unsigned i = 0; i < k - 1; ++i)
422 subEntity[lastIndex++] = 0;
423 subEntity[lastIndex++] = 1;
427 subEntity[lastIndex++] = 2;
428 for (
unsigned i = 0; i < k - 1; ++i)
429 subEntity[lastIndex++] = 3;
431 subEntity[lastIndex++] = 3;
433 assert(
power(k+1,dim)==lastIndex);
436 void setup3d(std::vector<unsigned int>& subEntity)
440 unsigned lastIndex=0;
442 const unsigned numIndices =
power(k+1,dim);
443 const unsigned numFaceIndices =
power(k+1,dim-1);
445 const unsigned numInnerEdgeDofs = k-1;
466 subEntity[lastIndex++] = 0;
467 for (
unsigned i = 0; i < numInnerEdgeDofs; ++i)
468 subEntity[lastIndex++] = 6;
470 subEntity[lastIndex++] = 1;
473 for (
unsigned e = 0; e < numInnerEdgeDofs; ++e) {
474 subEntity[lastIndex++] = 4;
475 for (
unsigned i = 0; i < numInnerEdgeDofs; ++i)
476 subEntity[lastIndex++] = 4;
477 subEntity[lastIndex++] = 5;
481 subEntity[lastIndex++] = 2;
482 for (
unsigned i = 0; i < k - 1; ++i)
483 subEntity[lastIndex++] = 7;
484 subEntity[lastIndex++] = 3;
486 assert(numFaceIndices==lastIndex);
490 for(
unsigned f = 0; f < numInnerEdgeDofs; ++f) {
493 subEntity[lastIndex++] = 0;
494 for (
unsigned i = 0; i < numInnerEdgeDofs; ++i)
495 subEntity[lastIndex++] = 2;
496 subEntity[lastIndex++] = 1;
499 for (
unsigned e = 0; e < numInnerEdgeDofs; ++e) {
500 subEntity[lastIndex++] = 0;
501 for (
unsigned i = 0; i < numInnerEdgeDofs; ++i)
502 subEntity[lastIndex++] = 0;
503 subEntity[lastIndex++] = 1;
507 subEntity[lastIndex++] = 2;
508 for (
unsigned i = 0; i < numInnerEdgeDofs; ++i)
509 subEntity[lastIndex++] = 3;
510 subEntity[lastIndex++] = 3;
512 assert(lastIndex==(f+1+1)*numFaceIndices);
517 subEntity[lastIndex++] = 4;
518 for (
unsigned i = 0; i < k - 1; ++i)
519 subEntity[lastIndex++] = 10;
520 subEntity[lastIndex++] = 5;
523 for (
unsigned e = 0; e < k - 1; ++e) {
524 subEntity[lastIndex++] = 8;
525 for (
unsigned i = 0; i < k - 1; ++i)
526 subEntity[lastIndex++] = 5;
527 subEntity[lastIndex++] = 9;
531 subEntity[lastIndex++] = 6;
532 for (
unsigned i = 0; i < k - 1; ++i)
533 subEntity[lastIndex++] = 11;
534 subEntity[lastIndex++] = 7;
536 assert(numIndices==lastIndex);
541 LagrangeCubeLocalCoefficients ()
546 localKeys_[0] = LocalKey(0,0,0);
552 for (std::size_t i=0; i<size(); i++)
553 localKeys_[i] = LocalKey(i,dim,0);
560 std::vector<unsigned int> codim(size());
562 for (std::size_t i=0; i<codim.size(); i++)
568 std::array<unsigned int,dim> mIdx = multiindex(i);
569 for (
unsigned int j=0; j<dim; j++)
570 if (mIdx[j]==0 or mIdx[j]==k)
579 std::vector<unsigned int> index(size());
581 for (std::size_t i=0; i<size(); i++)
585 std::array<unsigned int,dim> mIdx = multiindex(i);
587 for (
int j=dim-1; j>=0; j--)
588 if (mIdx[j]>0 && mIdx[j]<k)
589 index[i] = (k-1)*index[i] + (mIdx[j]-1);
593 std::vector<unsigned int> subEntity(size());
610 for (
size_t i=0; i<size(); i++)
611 localKeys_[i] = LocalKey(subEntity[i], codim[i], index[i]);
615 static constexpr std::size_t size ()
617 return power(k+1,dim);
621 const LocalKey& localKey (std::size_t i)
const
623 return localKeys_[i];
627 std::vector<LocalKey> localKeys_;
634 template<
class LocalBasis>
635 class LagrangeCubeLocalInterpolation
646 template<
typename F,
typename C>
647 void interpolate (
const F& ff, std::vector<C>& out)
const
649 constexpr auto dim = LocalBasis::Traits::dimDomain;
650 constexpr auto k = LocalBasis::order();
651 using D =
typename LocalBasis::Traits::DomainFieldType;
653 typename LocalBasis::Traits::DomainType x;
654 auto&& f = Impl::makeFunctionWithCallOperator<typename LocalBasis::Traits::DomainType>(ff);
656 out.resize(LocalBasis::size());
669 for (
unsigned int i=0; i<LocalBasis::size(); i++)
672 for (
int j=0; j<dim; j++)
673 x[j] = (i & (1<<j)) ? 1.0 : 0.0;
681 for (
unsigned int i=0; i<LocalBasis::size(); i++)
684 std::array<unsigned int,dim> alpha(LocalBasis::multiindex(i));
687 for (
unsigned int j=0; j<dim; j++)
688 x[j] = (1.0*alpha[j])/k;
707 template<
class D,
class R,
int dim,
int k>
714 Impl::LagrangeCubeLocalCoefficients<dim,k>,
715 Impl::LagrangeCubeLocalInterpolation<Impl::LagrangeCubeLocalBasis<D,R,dim,k> > >;
735 return coefficients_;
742 return interpolation_;
746 static constexpr std::size_t
size ()
748 return power(k+1,dim);
759 Impl::LagrangeCubeLocalBasis<D,R,dim,k> basis_;
760 Impl::LagrangeCubeLocalCoefficients<dim,k> coefficients_;
761 Impl::LagrangeCubeLocalInterpolation<Impl::LagrangeCubeLocalBasis<D,R,dim,k> > interpolation_;
Unique label for each type of entities that can occur in DUNE grids.
Definition: type.hh:123
Lagrange finite element for cubes with arbitrary compile-time dimension and polynomial order.
Definition: lagrangecube.hh:709
const Traits::LocalBasisType & localBasis() const
Returns the local basis, i.e., the set of shape functions.
Definition: lagrangecube.hh:726
LagrangeCubeLocalFiniteElement()
Default constructor.
Definition: lagrangecube.hh:722
const Traits::LocalInterpolationType & localInterpolation() const
Returns object that evaluates degrees of freedom.
Definition: lagrangecube.hh:740
static constexpr GeometryType type()
The reference element that the local finite element is defined on.
Definition: lagrangecube.hh:753
static constexpr std::size_t size()
The number of shape functions.
Definition: lagrangecube.hh:746
const Traits::LocalCoefficientsType & localCoefficients() const
Returns the assignment of the degrees of freedom to the element subentities.
Definition: lagrangecube.hh:733
Default exception for dummy implementations.
Definition: exceptions.hh:261
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:216
constexpr GeometryType cube(unsigned int dim)
Returns a GeometryType representing a hypercube of dimension dim.
Definition: type.hh:470
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:289
Some useful basic math stuff.
Dune namespace.
Definition: alignedallocator.hh:11
constexpr Mantissa power(Mantissa m, Exponent p)
Power method for integer exponents.
Definition: math.hh:73
static const ReferenceElement & cube()
get hypercube reference elements
Definition: referenceelements.hh:208
D DomainType
domain type
Definition: localbasis.hh:43
traits helper struct
Definition: localfiniteelementtraits.hh:11
LB LocalBasisType
Definition: localfiniteelementtraits.hh:14
LC LocalCoefficientsType
Definition: localfiniteelementtraits.hh:18
LI LocalInterpolationType
Definition: localfiniteelementtraits.hh:22