5#ifndef DUNE_MONOMIALBASIS_HH 
    6#define DUNE_MONOMIALBASIS_HH 
   14#include <dune/geometry/topologyfactory.hh> 
   16#include <dune/localfunctions/utility/field.hh> 
   17#include <dune/localfunctions/utility/multiindex.hh> 
   18#include <dune/localfunctions/utility/tensor.hh> 
   71  template< GeometryType::Id geometryId >
 
   72  class MonomialBasisSize;
 
   74  template< GeometryType::Id geometryId, 
class F >
 
   82  template< GeometryType::Id geometryId >
 
   83  class MonomialBasisSize
 
   85    typedef MonomialBasisSize< geometryId > This;
 
   88    static This &instance ()
 
   90      static This _instance;
 
   94    unsigned int maxOrder_;
 
   97    mutable unsigned int *sizes_;
 
  100    mutable unsigned int *numBaseFunctions_;
 
  105        numBaseFunctions_( 0 )
 
  110    ~MonomialBasisSize ()
 
  113      delete[] numBaseFunctions_;
 
  116    unsigned int operator() ( 
const unsigned int order )
 const 
  118      return numBaseFunctions_[ order ];
 
  121    unsigned int maxOrder()
 const 
  126    void computeSizes ( 
unsigned int order )
 
  128      if (order <= maxOrder_)
 
  134      delete[] numBaseFunctions_;
 
  135      sizes_            = 
new unsigned int[ order+1 ];
 
  136      numBaseFunctions_ = 
new unsigned int[ order+1 ];
 
  139      constexpr auto dim = geometry.dim();
 
  142      for( 
unsigned int k = 1; k <= order; ++k )
 
  145      std::fill(numBaseFunctions_, numBaseFunctions_+order+1, 1);
 
  147      for( 
int codim=dim-1; codim>=0; codim--)
 
  149        if (Impl::isPrism(geometry.id(),dim,codim))
 
  151          for( 
unsigned int k = 1; k <= order; ++k )
 
  153            sizes_[ k ]            = numBaseFunctions_[ k ] + k*sizes_[ k ];
 
  154            numBaseFunctions_[ k ] = numBaseFunctions_[ k-1 ] + sizes_[ k ];
 
  159          for( 
unsigned int k = 1; k <= order; ++k )
 
  161            sizes_[ k ]            = numBaseFunctions_[ k ];
 
  162            numBaseFunctions_[ k ] = numBaseFunctions_[ k-1 ] + sizes_[ k ];
 
  175  template< 
int mydim, 
int dim, 
class F >
 
  176  struct MonomialBasisHelper
 
  181    static void copy ( 
const unsigned int deriv, F *&wit, F *&rit,
 
  182                       const unsigned int numBaseFunctions, 
const F &z )
 
  185      MySize &mySize = MySize::instance();
 
  186      Size &
size = Size::instance();
 
  188      const F *
const rend = rit + 
size( deriv )*numBaseFunctions;
 
  189      for( ; rit != rend; )
 
  196        for( 
unsigned d = 1; d <= deriv; ++d )
 
  199          const F *
const derivEnd = rit + mySize.sizes_[ d ];
 
  203            const F *
const drend = rit + mySize.sizes_[ d ] - mySize.sizes_[ d-1 ];
 
  204            for( ; rit != drend ; ++rit, ++wit )
 
  208          for (
unsigned int j=1; j<d; ++j)
 
  210            const F *
const drend = rit + mySize.sizes_[ d-j ] - mySize.sizes_[ d-j-1 ];
 
  211            for( ; rit != drend ; ++prit, ++rit, ++wit )
 
  212              *wit = F(j) * *prit + z * *rit;
 
  214          *wit = F(d) * *prit + z * *rit;
 
  215          ++prit, ++rit, ++wit;
 
  216          assert(derivEnd == rit);
 
  217          rit += 
size.sizes_[d] - mySize.sizes_[d];
 
  218          prit += 
size.sizes_[d-1] - mySize.sizes_[d-1];
 
  219          const F *
const emptyWitEnd = wit + 
size.sizes_[d] - mySize.sizes_[d];
 
  220          for ( ; wit != emptyWitEnd; ++wit )
 
  232  template< GeometryType::Id geometryId, 
class F>
 
  233  class MonomialBasisImpl;
 
  236  class MonomialBasisImpl< GeometryTypes::
vertex, F >
 
  238    typedef MonomialBasisImpl< GeometryTypes::vertex, F > This;
 
  244    static const unsigned int dimDomain = geometry.
dim();
 
  246    typedef FieldVector< Field, dimDomain > DomainVector;
 
  249    friend class MonomialBasis< geometry.toId(), Field >;
 
  250    friend class MonomialBasisImpl< GeometryTypes::
prismaticExtension(geometry).toId(), Field >;
 
  251    friend class MonomialBasisImpl< GeometryTypes::conicalExtension(geometry).toId(), Field >;
 
  254    void evaluate ( const unsigned int deriv, const unsigned int order,
 
  255                    const FieldVector< Field, dimD > &x,
 
  256                    const unsigned int block, const unsigned int *const offsets,
 
  257                    Field *const values ) const
 
  259      *values = Unity< F >();
 
  260      F *
const end = values + block;
 
  261      for( Field *it = values+1 ; it != end; ++it )
 
  265    void integrate ( 
const unsigned int order,
 
  266                     const unsigned int *
const offsets,
 
  267                     Field *
const values )
 const 
  269      values[ 0 ] = Unity< Field >();
 
  273  template< GeometryType::Id geometryId, 
class F>
 
  274  class MonomialBasisImpl
 
  280    static constexpr GeometryType baseGeometry = Impl::getBase(geometry);
 
  282    static const unsigned int dimDomain = geometry.dim();
 
  284    typedef FieldVector< Field, dimDomain > DomainVector;
 
  287    friend class MonomialBasis< geometryId, Field >;
 
  288    friend class MonomialBasisImpl< GeometryTypes::
prismaticExtension(geometry).toId(), Field >;
 
  289    friend class MonomialBasisImpl< GeometryTypes::conicalExtension(geometry).toId(), Field >;
 
  291    typedef MonomialBasisSize< baseGeometry.toId() > BaseSize;
 
  292    typedef MonomialBasisSize< geometryId > Size;
 
  294    MonomialBasisImpl< baseGeometry.toId(), Field > baseBasis_;
 
  300    void evaluate ( 
const unsigned int deriv, 
const unsigned int order,
 
  301                    const FieldVector< Field, dimD > &x,
 
  302                    const unsigned int block, 
const unsigned int *
const offsets,
 
  303                    Field *
const values )
 const 
  305      if constexpr ( geometry.isPrismatic())
 
  306        evaluatePrismatic(deriv, order, x, block, offsets, values);
 
  308        evaluateConical(deriv, order, x, block, offsets, values);
 
  311    void integrate ( 
const unsigned int order,
 
  312                     const unsigned int *
const offsets,
 
  313                     Field *
const values )
 const 
  315      if constexpr ( geometry.isPrismatic())
 
  316        integratePrismatic(order, offsets, values);
 
  318        integrateConical(order, offsets, values);
 
  322    void evaluatePrismatic ( 
const unsigned int deriv, 
const unsigned int order,
 
  323                             const FieldVector< Field, dimD > &x,
 
  324                             const unsigned int block, 
const unsigned int *
const offsets,
 
  325                             Field *
const values )
 const 
  327      typedef MonomialBasisHelper< dimDomain, dimD, Field > Helper;
 
  328      const BaseSize &
size = BaseSize::instance();
 
  329      const_cast<BaseSize&
>(
size).computeSizes(order);
 
  331      const Field &z = x[ dimDomain-1 ];
 
  334      baseBasis_.evaluate( deriv, order, x, block, offsets, values );
 
  336      Field *row0 = values;
 
  337      for( 
unsigned int k = 1; k <= order; ++k )
 
  339        Field *row1 = values + block*offsets[ k-1 ];
 
  340        Field *wit = row1 + block*
size.sizes_[ k ];
 
  341        Helper::copy( deriv, wit, row1, k*
size.sizes_[ k ], z );
 
  342        Helper::copy( deriv, wit, row0, 
size( k-1 ), z );
 
  347    void integratePrismatic ( 
const unsigned int order,
 
  348                              const unsigned int *
const offsets,
 
  349                              Field *
const values )
 const 
  351      const BaseSize &
size = BaseSize::instance();
 
  352      const Size &mySize = Size::instance();
 
  354      baseBasis_.integrate( order, offsets, values );
 
  355      const unsigned int *
const baseSizes = 
size.sizes_;
 
  357      Field *row0 = values;
 
  358      for( 
unsigned int k = 1; k <= order; ++k )
 
  360        Field *
const row1begin = values + offsets[ k-1 ];
 
  361        Field *
const row1End = row1begin + mySize.sizes_[ k ];
 
  362        assert( (
unsigned int)(row1End - values) <= offsets[ k ] );
 
  364        Field *row1 = row1begin;
 
  365        Field *it = row1begin + baseSizes[ k ];
 
  366        for( 
unsigned int j = 1; j <= k; ++j )
 
  368          Field *
const end = it + baseSizes[ k ];
 
  369          assert( (
unsigned int)(end - values) <= offsets[ k ] );
 
  370          for( ; it != end; ++row1, ++it )
 
  371            *it = (Field( j ) / Field( j+1 )) * (*row1);
 
  373        for( ; it != row1End; ++row0, ++it )
 
  374          *it = (Field( k ) / Field( k+1 )) * (*row0);
 
  380    void evaluateSimplexBase ( 
const unsigned int deriv, 
const unsigned int order,
 
  381                               const FieldVector< Field, dimD > &x,
 
  382                               const unsigned int block, 
const unsigned int *
const offsets,
 
  384                               const BaseSize &
size )
 const 
  386      baseBasis_.evaluate( deriv, order, x, block, offsets, values );
 
  390    void evaluatePyramidBase ( 
const unsigned int deriv, 
const unsigned int order,
 
  391                               const FieldVector< Field, dimD > &x,
 
  392                               const unsigned int block, 
const unsigned int *
const offsets,
 
  394                               const BaseSize &
size )
 const 
  396      Field omz = Unity< Field >() - x[ dimDomain-1 ];
 
  398      if( Zero< Field >() < omz )
 
  400        const Field invomz = Unity< Field >() / omz;
 
  401        FieldVector< Field, dimD > y;
 
  402        for( 
unsigned int i = 0; i < dimDomain-1; ++i )
 
  403          y[ i ] = x[ i ] * invomz;
 
  406        baseBasis_.evaluate( deriv, order, y, block, offsets, values );
 
  409        for( 
unsigned int k = 1; k <= order; ++k )
 
  411          Field *it = values + block*offsets[ k-1 ];
 
  412          Field *
const end = it + block*
size.sizes_[ k ];
 
  413          for( ; it != end; ++it )
 
  421        *values = Unity< Field >();
 
  422        for( 
unsigned int k = 1; k <= order; ++k )
 
  424          Field *it = values + block*offsets[ k-1 ];
 
  425          Field *
const end = it + block*
size.sizes_[ k ];
 
  426          for( ; it != end; ++it )
 
  427            *it = Zero< Field >();
 
  433    void evaluateConical ( 
const unsigned int deriv, 
const unsigned int order,
 
  434                           const FieldVector< Field, dimD > &x,
 
  435                           const unsigned int block, 
const unsigned int *
const offsets,
 
  436                           Field *
const values )
 const 
  438      typedef MonomialBasisHelper< dimDomain, dimD, Field > Helper;
 
  439      const BaseSize &
size = BaseSize::instance();
 
  440      const_cast<BaseSize&
>(
size).computeSizes(order);
 
  442      if( geometry.isSimplex() )
 
  443        evaluateSimplexBase( deriv, order, x, block, offsets, values, 
size );
 
  445        evaluatePyramidBase( deriv, order, x, block, offsets, values, 
size );
 
  447      Field *row0 = values;
 
  448      for( 
unsigned int k = 1; k <= order; ++k )
 
  450        Field *row1 = values + block*offsets[ k-1 ];
 
  451        Field *wit = row1 + block*
size.sizes_[ k ];
 
  452        Helper::copy( deriv, wit, row0, 
size( k-1 ), x[ dimDomain-1 ] );
 
  457    void integrateConical ( 
const unsigned int order,
 
  458                            const unsigned int *
const offsets,
 
  459                            Field *
const values )
 const 
  461      const BaseSize &
size = BaseSize::instance();
 
  464      baseBasis_.integrate( order, offsets, values );
 
  466      const unsigned int *
const baseSizes = 
size.sizes_;
 
  469        Field *
const col0End = values + baseSizes[ 0 ];
 
  470        for( Field *it = values; it != col0End; ++it )
 
  471          *it *= Field( 1 ) /  Field( 
int(dimDomain) );
 
  474      Field *row0 = values;
 
  475      for( 
unsigned int k = 1; k <= order; ++k )
 
  477        const Field factor = (Field( 1 ) / Field( k + dimDomain ));
 
  479        Field *
const row1 = values+offsets[ k-1 ];
 
  480        Field *
const col0End = row1 + baseSizes[ k ];
 
  482        for( ; it != col0End; ++it )
 
  484        for( 
unsigned int i = 1; i <= k; ++i )
 
  486          Field *
const end = it + baseSizes[ k-i ];
 
  487          assert( (
unsigned int)(end - values) <= offsets[ k ] );
 
  488          for( ; it != end; ++row0, ++it )
 
  489            *it = (*row0) * (Field( i ) * factor);
 
  500  template< GeometryType::Id geometryId, 
class F >
 
  502    : 
public MonomialBasisImpl< geometryId, F >
 
  505    typedef MonomialBasis< geometryId, F > This;
 
  506    typedef MonomialBasisImpl< geometryId, F > Base;
 
  509    static const unsigned int dimension = Base::dimDomain;
 
  510    static const unsigned int dimRange = 1;
 
  512    typedef typename Base::Field Field;
 
  514    typedef typename Base::DomainVector DomainVector;
 
  518    typedef MonomialBasisSize<geometryId> Size;
 
  520    MonomialBasis (
unsigned int order)
 
  523        size_(Size::instance())
 
  528    const unsigned int *sizes ( 
unsigned int order )
 const 
  530      size_.computeSizes( order );
 
  531      return size_.numBaseFunctions_;
 
  534    const unsigned int *sizes ()
 const 
  536      return sizes( order_ );
 
  539    unsigned int size ()
 const 
  541      size_.computeSizes( order_ );
 
  542      return size_( order_ );
 
  545    unsigned int derivSize ( 
const unsigned int deriv )
 const 
  551    unsigned int order ()
 const 
  556    unsigned int topologyId ( )
 const 
  558      return geometry.id();
 
  561    void evaluate ( 
const unsigned int deriv, 
const DomainVector &x,
 
  562                    Field *
const values )
 const 
  564      Base::evaluate( deriv, order_, x, derivSize( deriv ), sizes( order_ ), values );
 
  567    template <
unsigned int deriv>
 
  568    void evaluate ( 
const DomainVector &x,
 
  569                    Field *
const values )
 const 
  571      evaluate( deriv, x, values );
 
  574    template<
unsigned int deriv, 
class Vector >
 
  575    void evaluate ( 
const DomainVector &x,
 
  576                    Vector &values )
 const 
  578      evaluate<deriv>(x,&(values[0]));
 
  580    template<
unsigned int deriv, DerivativeLayoutNS::DerivativeLayout layout >
 
  581    void evaluate ( 
const DomainVector &x,
 
  582                    Derivatives<Field,dimension,1,deriv,layout> *values )
 const 
  584      evaluate<deriv>(x,&(values->block()));
 
  586    template< 
unsigned int deriv >
 
  587    void evaluate ( 
const DomainVector &x,
 
  588                    FieldVector<Field,Derivatives<Field,dimension,1,deriv,DerivativeLayoutNS::value>::size> *values )
 const 
  590      evaluate(0,x,&(values[0][0]));
 
  593    template<
class Vector >
 
  594    void evaluate ( 
const DomainVector &x,
 
  595                    Vector &values )
 const 
  597      evaluate<0>(x,&(values[0]));
 
  600    template< 
class DVector, 
class RVector >
 
  601    void evaluate ( 
const DVector &x, RVector &values )
 const 
  603      assert( DVector::dimension == dimension);
 
  605      for( 
int d = 0; d < dimension; ++d )
 
  607      evaluate<0>( bx, values );
 
  610    void integrate ( Field *
const values )
 const 
  612      Base::integrate( order_, sizes( order_ ), values );
 
  614    template <
class Vector>
 
  615    void integrate ( Vector &values )
 const 
  617      integrate( &(values[ 0 ]) );
 
  620    MonomialBasis(
const This&);
 
  621    This& operator=(
const This&);
 
  631  template< 
int dim,
class F >
 
  632  class StandardMonomialBasis
 
  633    : 
public MonomialBasis< GeometryTypes::simplex(dim).toId() , F >
 
  635    typedef StandardMonomialBasis< dim, F > This;
 
  640    static const int dimension = dim;
 
  642    StandardMonomialBasis ( 
unsigned int order )
 
  652  template< 
int dim, 
class F >
 
  653  class StandardBiMonomialBasis
 
  654    : 
public MonomialBasis< GeometryTypes::cube(dim).toId() , F >
 
  656    typedef StandardBiMonomialBasis< dim, F > This;
 
  661    static const int dimension = dim;
 
  663    StandardBiMonomialBasis ( 
unsigned int order )
 
  673  template< 
int dim, 
class F >
 
  674  class VirtualMonomialBasis
 
  676    typedef VirtualMonomialBasis< dim, F > This;
 
  680    typedef F StorageField;
 
  681    static const int dimension = dim;
 
  682    static const unsigned int dimRange = 1;
 
  684    typedef FieldVector<Field,dimension> DomainVector;
 
  685    typedef FieldVector<Field,dimRange> RangeVector;
 
  687    explicit VirtualMonomialBasis(
const GeometryType& 
gt,
 
  689      : order_(order), geometry_(
gt) {}
 
  691    virtual ~VirtualMonomialBasis() {}
 
  693    virtual const unsigned int *sizes ( ) 
const = 0;
 
  695    unsigned int size ( )
 const 
  697      return sizes( )[ order_ ];
 
  700    unsigned int order ()
 const 
  710    virtual void evaluate ( 
const unsigned int deriv, 
const DomainVector &x,
 
  711                            Field *
const values ) 
const = 0;
 
  712    template < 
unsigned int deriv >
 
  713    void evaluate ( 
const DomainVector &x,
 
  714                    Field *
const values )
 const 
  716      evaluate( deriv, x, values );
 
  718    template < 
unsigned int deriv, 
int size >
 
  719    void evaluate ( 
const DomainVector &x,
 
  722      evaluate( deriv, x, &(values[0][0]) );
 
  724    template<
unsigned int deriv, DerivativeLayoutNS::DerivativeLayout layout >
 
  725    void evaluate ( 
const DomainVector &x,
 
  726                    Derivatives<Field,dimension,1,deriv,layout> *values )
 const 
  728      evaluate<deriv>(x,&(values->block()));
 
  730    template <
unsigned int deriv, 
class Vector>
 
  731    void evaluate ( 
const DomainVector &x,
 
  732                    Vector &values )
 const 
  734      evaluate<deriv>( x, &(values[ 0 ]) );
 
  736    template< 
class Vector >
 
  737    void evaluate ( 
const DomainVector &x,
 
  738                    Vector &values )
 const 
  740      evaluate<0>(x,values);
 
  742    template< 
class DVector, 
class RVector >
 
  743    void evaluate ( 
const DVector &x, RVector &values )
 const 
  745      assert( DVector::dimension == dimension);
 
  747      for( 
int d = 0; d < dimension; ++d )
 
  749      evaluate<0>( bx, values );
 
  751    template< 
unsigned int deriv, 
class DVector, 
class RVector >
 
  752    void evaluate ( 
const DVector &x, RVector &values )
 const 
  754      assert( DVector::dimension == dimension);
 
  756      for( 
int d = 0; d < dimension; ++d )
 
  758      evaluate<deriv>( bx, values );
 
  761    virtual void integrate ( Field *
const values ) 
const = 0;
 
  762    template <
class Vector>
 
  763    void integrate ( Vector &values )
 const 
  765      integrate( &(values[ 0 ]) );
 
  772  template< GeometryType::Id geometryId, 
class F >
 
  773  class VirtualMonomialBasisImpl
 
  774    : 
public VirtualMonomialBasis< static_cast<GeometryType>(geometryId).dim(), F >
 
  777    typedef VirtualMonomialBasis< geometry.dim(), F > Base;
 
  778    typedef VirtualMonomialBasisImpl< geometryId, F > This;
 
  781    typedef typename Base::Field Field;
 
  782    typedef typename Base::DomainVector DomainVector;
 
  784    VirtualMonomialBasisImpl(
unsigned int order)
 
  785      : Base(geometry,order), basis_(order)
 
  788    const unsigned int *sizes ( )
 const 
  790      return basis_.sizes(order_);
 
  793    void evaluate ( 
const unsigned int deriv, 
const DomainVector &x,
 
  794                    Field *
const values )
 const 
  796      basis_.evaluate(deriv,x,values);
 
  799    void integrate ( Field *
const values )
 const 
  801      basis_.integrate(values);
 
  805    MonomialBasis<geometryId,Field> basis_;
 
  812  template< 
int dim, 
class F >
 
  813  struct MonomialBasisFactory
 
  815    static const unsigned int dimension = dim;
 
  816    typedef F StorageField;
 
  818    typedef unsigned int Key;
 
  819    typedef const VirtualMonomialBasis< dimension, F > Object;
 
  821    template < 
int dd, 
class FF >
 
  822    struct EvaluationBasisFactory
 
  824      typedef MonomialBasisFactory<dd,FF> Type;
 
  827    template< GeometryType::Id geometryId >
 
  828    static Object* create ( 
const Key &order )
 
  830      return new VirtualMonomialBasisImpl< geometryId, StorageField >( order );
 
  832    static void release( Object *
object ) { 
delete object; }
 
  840  template< 
int dim, 
class SF >
 
  841  struct MonomialBasisProvider
 
  842    : 
public TopologySingletonFactory< MonomialBasisFactory< dim, SF > >
 
  844    static const unsigned int dimension = dim;
 
  845    typedef SF StorageField;
 
  846    template < 
int dd, 
class FF >
 
  847    struct EvaluationBasisFactory
 
  849      typedef MonomialBasisProvider<dd,FF> Type;
 
vector space out of a tensor product of fields.
Definition: fvector.hh:97
 
constexpr Id toId() const
Create an Id representation of this GeometryType.
Definition: type.hh:210
 
constexpr unsigned int dim() const
Return dimension of the type.
Definition: type.hh:360
 
GeometryType
Type representing VTK's entity geometry types.
Definition: common.hh:132
 
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.
 
bool gt(const T &first, const T &second, typename EpsilonType< T >::Type epsilon)
test if first greater than second
Definition: float_cmp.cc:158
 
constexpr GeometryType cube(unsigned int dim)
Returns a GeometryType representing a hypercube of dimension dim.
Definition: type.hh:462
 
constexpr GeometryType simplex(unsigned int dim)
Returns a GeometryType representing a simplex of dimension dim.
Definition: type.hh:453
 
constexpr GeometryType vertex
GeometryType representing a vertex.
Definition: type.hh:492
 
constexpr GeometryType prismaticExtension(const GeometryType >)
Return GeometryType of a prismatic construction with gt as base
Definition: type.hh:483
 
Dune namespace.
Definition: alignedallocator.hh:13
 
void field_cast(const F1 &f1, F2 &f2)
a helper class to cast from one field to another
Definition: field.hh:160
 
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
 
A unique label for each type of element that can occur in a grid.