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:92
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.