1#ifndef DUNE_FEM_SHAPEFUNCTIONSET_TENSORPRODUCT_HH
2#define DUNE_FEM_SHAPEFUNCTIONSET_TENSORPRODUCT_HH
11#include <dune/fem/common/forloop.hh>
13#include <dune/common/hybridutilities.hh>
15#include <dune/fem/common/coordinate.hh>
26 template<
class FunctionSpace,
class ShapeFunctionSetTuple >
27 class TensorProductShapeFunctionSet
29 typedef TensorProductShapeFunctionSet< FunctionSpace, ShapeFunctionSetTuple > ThisType;
32 "dimDomain of FunctionSpace must coincide with length of ShapeFunctionSetTuple." );
34 "FunctionSpace must be scalar (i.e., dimRange = 1)." );
38 template<
int i >
struct Size;
39 template<
int i >
struct EvaluateAll;
40 template<
int i >
struct JacobianAll;
41 template<
int i >
struct HessianAll;
47 typedef ShapeFunctionSetTuple ShapeFunctionSetTupleType;
57 TensorProductShapeFunctionSet () =
default;
59 explicit TensorProductShapeFunctionSet (
const ShapeFunctionSetTupleType &shapeFunctionSetTuple );
60 ~TensorProductShapeFunctionSet ();
62 TensorProductShapeFunctionSet (
const ThisType &other );
63 const ThisType &operator= (
const ThisType &other );
67 std::size_t
size ()
const;
69 template<
class Po
int,
class Functor >
70 void evaluateEach (
const Point &x, Functor functor )
const;
72 template<
class Po
int,
class Functor >
73 void jacobianEach (
const Point &x, Functor functor )
const;
75 template<
class Po
int,
class Functor >
76 void hessianEach (
const Point &x, Functor functor )
const;
79 template<
class Functor >
80 void doEvaluateEach (
int d, RangeType value, std::size_t &index,
const RangeFieldType *buffer, Functor functor )
const;
81 template<
class Functor >
82 void doJacobianEach (
int d, JacobianRangeType jacobian, std::size_t &index,
const RangeFieldType *buffer, Functor functor )
const;
83 template<
class Functor >
84 void doHessianEach (
int d, HessianRangeType hessian, std::size_t &index,
const RangeFieldType *buffer, Functor functor )
const;
86 ShapeFunctionSetTuple shapeFunctionSetTuple_;
87 std::array< std::size_t, dimension > sizes_;
88 RangeFieldType *buffer_;
96 template<
class FunctionSpace,
class ShapeFunctionSetTuple >
97 struct TensorProductShapeFunctionSet< FunctionSpace, ShapeFunctionSetTuple >::Assign
99 explicit Assign ( RangeFieldType *buffer ) : buffer_( buffer ) {}
101 void operator() (
const std::size_t i,
const RangeFieldType &value )
103 buffer_[ i ] = value;
107 void operator() (
const std::size_t i,
const FieldVector< T, 1 > &value )
109 (*this)( i, value[ 0 ] );
113 void operator() (
const std::size_t i,
const FieldMatrix< T, 1, 1 > &value )
115 (*this)( i, value[ 0 ][ 0 ] );
119 RangeFieldType *buffer_;
127 template<
class FunctionSpace,
class ShapeFunctionSetTuple >
129 struct TensorProductShapeFunctionSet< FunctionSpace, ShapeFunctionSetTuple >::Size
131 static void apply (
const ShapeFunctionSetTuple &tuple, std::array< std::size_t, FunctionSpace::dimDomain > &
size )
133 size[ i ] = std::get< i >( tuple ).size();
142 template<
class FunctionSpace,
class ShapeFunctionSetTuple >
144 struct TensorProductShapeFunctionSet< FunctionSpace, ShapeFunctionSetTuple >::EvaluateAll
146 static void apply (
const ShapeFunctionSetTuple &tuple,
const DomainType &x, RangeFieldType *&it )
149 std::get< i >( tuple ).evaluateEach( xi, Assign( it ) );
150 it += std::get< i >( tuple ).size();
159 template<
class FunctionSpace,
class ShapeFunctionSetTuple >
161 struct TensorProductShapeFunctionSet< FunctionSpace, ShapeFunctionSetTuple >::JacobianAll
163 static void apply (
const ShapeFunctionSetTuple &tuple,
const DomainType &x, RangeFieldType *&it )
166 const std::size_t
size = std::get< i >( tuple ).size();
167 std::get< i >( tuple ).evaluateEach( xi, Assign( it ) );
168 std::get< i >( tuple ).jacobianEach( xi, Assign( it+
size ) );
178 template<
class FunctionSpace,
class ShapeFunctionSetTuple >
180 struct TensorProductShapeFunctionSet< FunctionSpace, ShapeFunctionSetTuple >::HessianAll
182 static void apply (
const ShapeFunctionSetTuple &tuple,
const DomainType &x, RangeFieldType *&it )
185 const std::size_t
size = std::get< i >( tuple ).size();
186 std::get< i >( tuple ).evaluateEach( xi, Assign( it ) );
187 std::get< i >( tuple ).jacobianEach( xi, Assign( it+
size ) );
188 std::get< i >( tuple ).hessianEach( xi, Assign( it+2*
size ) );
198 template<
class FunctionSpace,
class ShapeFunctionSetTuple >
199 inline TensorProductShapeFunctionSet< FunctionSpace, ShapeFunctionSetTuple >
200 ::TensorProductShapeFunctionSet (
const ShapeFunctionSetTupleType &shapeFunctionSetTuple )
201 : shapeFunctionSetTuple_( shapeFunctionSetTuple )
203 Fem::ForLoop< Size, 0, dimension-1 >::apply( shapeFunctionSetTuple_, sizes_ );
204 std::size_t buffer_size = 0;
205 for(
int i = 0; i < dimension; ++i )
206 buffer_size += sizes_[ i ];
207 buffer_ =
new RangeFieldType[ 3*buffer_size ];
211 template<
class FunctionSpace,
class ShapeFunctionSetTuple >
212 inline TensorProductShapeFunctionSet< FunctionSpace, ShapeFunctionSetTuple >
213 ::~TensorProductShapeFunctionSet ()
219 template<
class FunctionSpace,
class ShapeFunctionSetTuple >
220 inline TensorProductShapeFunctionSet< FunctionSpace, ShapeFunctionSetTuple >
221 ::TensorProductShapeFunctionSet (
const ThisType &other )
222 : shapeFunctionSetTuple_( other.shapeFunctionSetTuple_ )
224 std::size_t buffer_size = 0;
225 for(
int i = 0; i < dimension; ++i )
227 sizes_[ i ] = other.sizes_[ i ];
228 buffer_size += sizes_[ i ];
230 buffer_ =
new RangeFieldType[ 3*buffer_size ];
234 template<
class FunctionSpace,
class ShapeFunctionSetTuple >
235 inline const typename TensorProductShapeFunctionSet< FunctionSpace, ShapeFunctionSetTuple >::ThisType &
236 TensorProductShapeFunctionSet< FunctionSpace, ShapeFunctionSetTuple >
237 ::operator= (
const ThisType &other )
243 shapeFunctionSetTuple_ = other.shapeFunctionSetTuple_;
244 std::size_t buffer_size = 0;
245 for(
int i = 0; i < dimension; ++i )
247 sizes_[ i ] = other.sizes_[ i ];
248 buffer_size += sizes_[ i ];
250 buffer_ =
new RangeFieldType[ 3*buffer_size ];
255 template<
class FunctionSpace,
class ShapeFunctionSetTuple >
256 inline int TensorProductShapeFunctionSet< FunctionSpace, ShapeFunctionSetTuple >::order ()
const
259 Hybrid::forEach( std::make_index_sequence< std::tuple_size< ShapeFunctionSetTupleType >::value >{},
260 [ & ](
auto i ){ value = std::max( value, std::get< i >( shapeFunctionSetTuple_ ).order() ); } );
265 template<
class FunctionSpace,
class ShapeFunctionSetTuple >
267 TensorProductShapeFunctionSet< FunctionSpace, ShapeFunctionSetTuple >::size ()
const
269 std::size_t size( 1 );
270 for(
int i = 0; i < dimension; ++i )
276 template<
class FunctionSpace,
class ShapeFunctionSetTuple >
277 template<
class Po
int,
class Functor >
278 inline void TensorProductShapeFunctionSet< FunctionSpace, ShapeFunctionSetTuple >
279 ::evaluateEach (
const Point &x, Functor functor )
const
281 RangeFieldType *it = buffer_;
282 Fem::ForLoop< EvaluateAll, 0, dimension-1 >::apply( shapeFunctionSetTuple_,
coordinate( x ), it );
284 std::size_t index = 0;
285 doEvaluateEach( 0, RangeType( RangeFieldType( 1 ) ), index, buffer_, functor );
289 template<
class FunctionSpace,
class ShapeFunctionSetTuple >
290 template<
class Po
int,
class Functor >
291 inline void TensorProductShapeFunctionSet< FunctionSpace, ShapeFunctionSetTuple >
292 ::jacobianEach (
const Point &x, Functor functor )
const
294 RangeFieldType *it = buffer_;
295 Fem::ForLoop< JacobianAll, 0, dimension-1 >::apply( shapeFunctionSetTuple_,
coordinate( x ), it );
297 std::size_t index = 0;
298 JacobianRangeType jacobian;
299 for(
int i = 0; i < dimension; ++i )
300 jacobian[ 0 ][ i ] = RangeFieldType( 1 );
301 doJacobianEach( 0, jacobian, index, buffer_, functor );
305 template<
class FunctionSpace,
class ShapeFunctionSetTuple >
306 template<
class Po
int,
class Functor >
307 inline void TensorProductShapeFunctionSet< FunctionSpace, ShapeFunctionSetTuple >
308 ::hessianEach (
const Point &x, Functor functor )
const
310 RangeFieldType *it = buffer_;
311 Fem::ForLoop< HessianAll, 0, dimension-1 >::apply( shapeFunctionSetTuple_,
coordinate( x ), it );
313 std::size_t index = 0;
314 HessianRangeType hessian;
315 for(
int i = 0; i < dimension; ++i )
316 for(
int j = 0; j < dimension; ++j )
317 hessian[ 0 ][ i ][ j ] = RangeFieldType( 1 );
318 doHessianEach( 0, hessian, index, buffer_, functor );
322 template<
class FunctionSpace,
class ShapeFunctionSetTuple >
323 template<
class Functor >
324 inline void TensorProductShapeFunctionSet< FunctionSpace, ShapeFunctionSetTuple >
325 ::doEvaluateEach (
int d, RangeType value, std::size_t &index,
const RangeFieldType *buffer, Functor functor )
const
329 for( std::size_t i = 0; i < sizes_[ d ]; ++i )
331 RangeType v( value );
332 v[ 0 ] *= buffer[ i ];
333 doEvaluateEach( d+1, v, index, buffer+sizes_[ d ], functor );
337 functor( index++, value );
341 template<
class FunctionSpace,
class ShapeFunctionSetTuple >
342 template<
class Functor >
343 inline void TensorProductShapeFunctionSet< FunctionSpace, ShapeFunctionSetTuple >
344 ::doJacobianEach (
int d, JacobianRangeType jacobian, std::size_t &index,
const RangeFieldType *buffer, Functor functor )
const
348 for( std::size_t i = 0; i < sizes_[ d ]; ++i )
350 JacobianRangeType j( jacobian );
351 j[ 0 ][ d ] *= buffer[ i + sizes_[ d ] ];
352 for(
int k = 1; k < dimension; ++k )
353 j[ 0 ][ (d+k)%dimension ] *= buffer[ i ];
354 doJacobianEach( d+1, j, index, buffer+2*sizes_[ d ], functor );
358 functor( index++, jacobian );
362 template<
class FunctionSpace,
class ShapeFunctionSetTuple >
363 template<
class Functor >
364 inline void TensorProductShapeFunctionSet< FunctionSpace, ShapeFunctionSetTuple >
365 ::doHessianEach (
int d, HessianRangeType hessian, std::size_t &index,
const RangeFieldType *buffer, Functor functor )
const
369 for( std::size_t i = 0; i < sizes_[ d ]; ++i )
371 HessianRangeType h( hessian );
372 h[ 0 ][ d ][ d ] *= buffer[ i + 2*sizes_[ d ] ];
373 for(
int j = 1; j < dimension; ++j )
375 h[ 0 ][ (d+j)%dimension ][ d ] *= buffer[ i * sizes_[ d ] ];
376 h[ 0 ][ d ][ (d+j)%dimension ] *= buffer[ i * sizes_[ d ] ];
377 for(
int k = 1; k < dimension; ++k )
378 h[ 0 ][ (d+j)%dimension ][ (d+k)%dimension ] *= buffer[ i ];
380 doHessianEach( d+1, h, index, buffer+3*sizes_[ d ], functor );
384 functor( index++, hessian );
Definition: explicitfieldvector.hh:75
FunctionSpaceTraits::DomainFieldType DomainFieldType
Intrinsic type used for values in the domain field (usually a double)
Definition: functionspaceinterface.hh:60
FunctionSpaceTraits::RangeType RangeType
Type of range vector (using type of range field) has a Dune::FieldVector type interface.
Definition: functionspaceinterface.hh:71
@ dimDomain
dimension of domain vector space
Definition: functionspaceinterface.hh:46
@ dimRange
dimension of range vector space
Definition: functionspaceinterface.hh:48
FunctionSpaceTraits::LinearMappingType JacobianRangeType
Intrinsic type used for the jacobian values has a Dune::FieldMatrix type interface.
Definition: functionspaceinterface.hh:75
FunctionSpaceTraits::DomainType DomainType
Type of domain vector (using type of domain field) has a Dune::FieldVector type interface.
Definition: functionspaceinterface.hh:67
FunctionSpaceTraits::RangeFieldType RangeFieldType
Intrinsic type used for values in the range field (usually a double)
Definition: functionspaceinterface.hh:63
A vector valued function space.
Definition: functionspace.hh:60
static Quadrature::CoordinateType coordinate(const QuadraturePointWrapper< Quadrature > &x)
extract the real coordinate from a point
Definition: quadrature.hh:91
vector space out of a tensor product of fields.
Definition: fvector.hh:91
Contains utility classes which can be used with std::tuple.
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.
constexpr void forEach(Range &&range, F &&f)
Range based for loop.
Definition: hybridutilities.hh:256
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