dune-fem  2.4.1-rc
tensorproduct.hh
Go to the documentation of this file.
1 #ifndef DUNE_FEM_SHAPEFUNCTIONSET_TENSORPRODUCT_HH
2 #define DUNE_FEM_SHAPEFUNCTIONSET_TENSORPRODUCT_HH
3 
4 // C++ includes
5 #include <algorithm>
6 #include <cstddef>
7 #include <tuple>
8 #include <array>
9 
10 // dune-common includes
11 #include <dune/common/fmatrix.hh>
12 #include <dune/common/forloop.hh>
13 #include <dune/common/fvector.hh>
14 #include <dune/common/tuples.hh>
15 #include <dune/common/tupleutility.hh>
16 
18 
19 namespace Dune
20 {
21 
22  namespace Fem
23  {
24 
25  // TensorProductShapeFunctionSet
26  // -----------------------------
27 
28  template< class FunctionSpace, class ShapeFunctionSetTuple >
30  {
32 
33  static_assert( (FunctionSpace::dimDomain == std::tuple_size< ShapeFunctionSetTuple >::value),
34  "dimDomain of FunctionSpace must coincide with length of ShapeFunctionSetTuple." );
35  static_assert( (FunctionSpace::dimRange == 1),
36  "FunctionSpace must be scalar (i.e., dimRange = 1)." );
37 
38  struct Assign;
39  struct Order;
40 
41  template< int i > struct Size;
42  template< int i > struct EvaluateAll;
43  template< int i > struct JacobianAll;
44  template< int i > struct HessianAll;
45 
46  static const int dimension = FunctionSpace::dimDomain;
47 
48  public:
50  typedef ShapeFunctionSetTuple ShapeFunctionSetTupleType;
51 
54 
59 
60  TensorProductShapeFunctionSet () = default;
61 
62  explicit TensorProductShapeFunctionSet ( const ShapeFunctionSetTupleType &shapeFunctionSetTuple );
64 
65  TensorProductShapeFunctionSet ( const ThisType &other );
66  const ThisType &operator= ( const ThisType &other );
67 
68  int order () const;
69 
70  std::size_t size () const;
71 
72  template< class Point, class Functor >
73  void evaluateEach ( const Point &x, Functor functor ) const;
74 
75  template< class Point, class Functor >
76  void jacobianEach ( const Point &x, Functor functor ) const;
77 
78  template< class Point, class Functor >
79  void hessianEach ( const Point &x, Functor functor ) const;
80 
81  private:
82  template< class Functor >
83  void doEvaluateEach ( int d, RangeType value, std::size_t &index, const RangeFieldType *buffer, Functor functor ) const;
84  template< class Functor >
85  void doJacobianEach ( int d, JacobianRangeType jacobian, std::size_t &index, const RangeFieldType *buffer, Functor functor ) const;
86  template< class Functor >
87  void doHessianEach ( int d, HessianRangeType hessian, std::size_t &index, const RangeFieldType *buffer, Functor functor ) const;
88 
89  ShapeFunctionSetTuple shapeFunctionSetTuple_;
90  std::array< std::size_t, dimension > sizes_;
91  RangeFieldType *buffer_;
92  };
93 
94 
95 
96  // TensorProductShapeFunctionSet::Assign
97  // -------------------------------------
98 
99  template< class FunctionSpace, class ShapeFunctionSetTuple >
100  struct TensorProductShapeFunctionSet< FunctionSpace, ShapeFunctionSetTuple >::Assign
101  {
102  explicit Assign ( RangeFieldType *buffer ) : buffer_( buffer ) {}
103 
104  void operator() ( const std::size_t i, const RangeFieldType &value )
105  {
106  buffer_[ i ] = value;
107  }
108 
109  template< class T >
110  void operator() ( const std::size_t i, const FieldVector< T, 1 > &value )
111  {
112  (*this)( i, value[ 0 ] );
113  }
114 
115  template< class T >
116  void operator() ( const std::size_t i, const FieldMatrix< T, 1, 1 > &value )
117  {
118  (*this)( i, value[ 0 ][ 0 ] );
119  }
120 
121  private:
122  RangeFieldType *buffer_;
123  };
124 
125 
126 
127  // TensorProductShapeFunctionSet::Order
128  // ------------------------------------
129 
130  template< class FunctionSpace, class ShapeFunctionSetTuple >
131  struct TensorProductShapeFunctionSet< FunctionSpace, ShapeFunctionSetTuple >::Order
132  {
133  Order () : order_( 0 ) {}
134 
135  template< class ShapeFunctionSet >
136  void visit ( const ShapeFunctionSet &shapeFunctionSet )
137  {
138  order_ = std::max( order_, shapeFunctionSet.order() );
139  }
140 
141  operator int() const { return order_; }
142  private:
143  int order_;
144  };
145 
146 
147 
148  // TensorProductShapeFunctionSet::Size
149  // -----------------------------------
150 
151  template< class FunctionSpace, class ShapeFunctionSetTuple >
152  template< int i >
153  struct TensorProductShapeFunctionSet< FunctionSpace, ShapeFunctionSetTuple >::Size
154  {
155  static void apply ( const ShapeFunctionSetTuple &tuple, std::array< std::size_t, FunctionSpace::dimDomain > &size )
156  {
157  size[ i ] = std::get< i >( tuple ).size();
158  }
159  };
160 
161 
162 
163  // TensorProductShapeFunctionSet::EvaluateAll
164  // ------------------------------------------
165 
166  template< class FunctionSpace, class ShapeFunctionSetTuple >
167  template< int i >
168  struct TensorProductShapeFunctionSet< FunctionSpace, ShapeFunctionSetTuple >::EvaluateAll
169  {
170  static void apply ( const ShapeFunctionSetTuple &tuple, const DomainType &x, RangeFieldType *&it )
171  {
172  Dune::FieldVector< DomainFieldType, 1 > xi( x[ i ] );
173  std::get< i >( tuple ).evaluateEach( xi, Assign( it ) );
174  it += std::get< i >( tuple ).size();
175  }
176  };
177 
178 
179 
180  // TensorProductShapeFunctionSet::JacobianAll
181  // ------------------------------------------
182 
183  template< class FunctionSpace, class ShapeFunctionSetTuple >
184  template< int i >
185  struct TensorProductShapeFunctionSet< FunctionSpace, ShapeFunctionSetTuple >::JacobianAll
186  {
187  static void apply ( const ShapeFunctionSetTuple &tuple, const DomainType &x, RangeFieldType *&it )
188  {
189  Dune::FieldVector< DomainFieldType, 1 > xi( x[ i ] );
190  const std::size_t size = std::get< i >( tuple ).size();
191  std::get< i >( tuple ).evaluateEach( xi, Assign( it ) );
192  std::get< i >( tuple ).jacobianEach( xi, Assign( it+size ) );
193  it += 2*size;
194  }
195  };
196 
197 
198 
199  // TensorProductShapeFunctionSet::HessianAll
200  // -----------------------------------------
201 
202  template< class FunctionSpace, class ShapeFunctionSetTuple >
203  template< int i >
204  struct TensorProductShapeFunctionSet< FunctionSpace, ShapeFunctionSetTuple >::HessianAll
205  {
206  static void apply ( const ShapeFunctionSetTuple &tuple, const DomainType &x, RangeFieldType *&it )
207  {
208  Dune::FieldVector< DomainFieldType, 1 > xi( x[ i ] );
209  const std::size_t size = std::get< i >( tuple ).size();
210  std::get< i >( tuple ).evaluateEach( xi, Assign( it ) );
211  std::get< i >( tuple ).jacobianEach( xi, Assign( it+size ) );
212  std::get< i >( tuple ).hessianEach( xi, Assign( it+2*size ) );
213  it += 3*size;
214  }
215  };
216 
217 
218 
219  // Implementation of TensorProductShapeFunctionSet
220  // -----------------------------------------------
221 
222  template< class FunctionSpace, class ShapeFunctionSetTuple >
225  : shapeFunctionSetTuple_( shapeFunctionSetTuple )
226  {
227  ForLoop< Size, 0, dimension-1 >::apply( shapeFunctionSetTuple_, sizes_ );
228  std::size_t buffer_size = 0;
229  for( int i = 0; i < dimension; ++i )
230  buffer_size += sizes_[ i ];
231  buffer_ = new RangeFieldType[ 3*buffer_size ];
232  }
233 
234 
235  template< class FunctionSpace, class ShapeFunctionSetTuple >
238  {
239  delete[]( buffer_ );
240  }
241 
242 
243  template< class FunctionSpace, class ShapeFunctionSetTuple >
246  : shapeFunctionSetTuple_( other.shapeFunctionSetTuple_ )
247  {
248  std::size_t buffer_size = 0;
249  for( int i = 0; i < dimension; ++i )
250  {
251  sizes_[ i ] = other.sizes_[ i ];
252  buffer_size += sizes_[ i ];
253  }
254  buffer_ = new RangeFieldType[ 3*buffer_size ];
255  }
256 
257 
258  template< class FunctionSpace, class ShapeFunctionSetTuple >
261  ::operator= ( const ThisType &other )
262  {
263  if( this == &other )
264  return *this;
265  delete[]( buffer_ );
266 
267  shapeFunctionSetTuple_ = other.shapeFunctionSetTuple_;
268  std::size_t buffer_size = 0;
269  for( int i = 0; i < dimension; ++i )
270  {
271  sizes_[ i ] = other.sizes_[ i ];
272  buffer_size += sizes_[ i ];
273  }
274  buffer_ = new RangeFieldType[ 3*buffer_size ];
275  return *this;
276  }
277 
278 
279  template< class FunctionSpace, class ShapeFunctionSetTuple >
281  {
282  Dune::ForEachValue< const ShapeFunctionSetTupleType > forEach( shapeFunctionSetTuple_ );
283  Order functor;
284  forEach.apply( functor );
285  return functor;
286  }
287 
288 
289  template< class FunctionSpace, class ShapeFunctionSetTuple >
290  inline std::size_t
292  {
293  std::size_t size( 1 );
294  for( int i = 0; i < dimension; ++i )
295  size *= sizes_[ i ];
296  return size;
297  }
298 
299 
300  template< class FunctionSpace, class ShapeFunctionSetTuple >
301  template< class Point, class Functor >
303  ::evaluateEach ( const Point &x, Functor functor ) const
304  {
305  RangeFieldType *it = buffer_;
306  ForLoop< EvaluateAll, 0, dimension-1 >::apply( shapeFunctionSetTuple_, coordinate( x ), it );
307 
308  std::size_t index = 0;
309  doEvaluateEach( 0, RangeType( RangeFieldType( 1 ) ), index, buffer_, functor );
310  }
311 
312 
313  template< class FunctionSpace, class ShapeFunctionSetTuple >
314  template< class Point, class Functor >
316  ::jacobianEach ( const Point &x, Functor functor ) const
317  {
318  RangeFieldType *it = buffer_;
319  ForLoop< JacobianAll, 0, dimension-1 >::apply( shapeFunctionSetTuple_, coordinate( x ), it );
320 
321  std::size_t index = 0;
322  JacobianRangeType jacobian;
323  for( int i = 0; i < dimension; ++i )
324  jacobian[ 0 ][ i ] = RangeFieldType( 1 );
325  doJacobianEach( 0, jacobian, index, buffer_, functor );
326  }
327 
328 
329  template< class FunctionSpace, class ShapeFunctionSetTuple >
330  template< class Point, class Functor >
332  ::hessianEach ( const Point &x, Functor functor ) const
333  {
334  RangeFieldType *it = buffer_;
335  ForLoop< HessianAll, 0, dimension-1 >::apply( shapeFunctionSetTuple_, coordinate( x ), it );
336 
337  std::size_t index = 0;
338  HessianRangeType hessian;
339  for( int i = 0; i < dimension; ++i )
340  for( int j = 0; j < dimension; ++j )
341  hessian[ 0 ][ i ][ j ] = RangeFieldType( 1 );
342  doHessianEach( 0, hessian, index, buffer_, functor );
343  }
344 
345 
346  template< class FunctionSpace, class ShapeFunctionSetTuple >
347  template< class Functor >
349  ::doEvaluateEach ( int d, RangeType value, std::size_t &index, const RangeFieldType *buffer, Functor functor ) const
350  {
351  if( d < dimension )
352  {
353  for( std::size_t i = 0; i < sizes_[ d ]; ++i )
354  {
355  RangeType v( value );
356  v[ 0 ] *= buffer[ i ];
357  doEvaluateEach( d+1, v, index, buffer+sizes_[ d ], functor );
358  }
359  }
360  else
361  functor( index++, value );
362  }
363 
364 
365  template< class FunctionSpace, class ShapeFunctionSetTuple >
366  template< class Functor >
368  ::doJacobianEach ( int d, JacobianRangeType jacobian, std::size_t &index, const RangeFieldType *buffer, Functor functor ) const
369  {
370  if( d < dimension )
371  {
372  for( std::size_t i = 0; i < sizes_[ d ]; ++i )
373  {
374  JacobianRangeType j( jacobian );
375  j[ 0 ][ d ] *= buffer[ i + sizes_[ d ] ];
376  for( int k = 1; k < dimension; ++k )
377  j[ 0 ][ (d+k)%dimension ] *= buffer[ i ];
378  doJacobianEach( d+1, j, index, buffer+2*sizes_[ d ], functor );
379  }
380  }
381  else
382  functor( index++, jacobian );
383  }
384 
385 
386  template< class FunctionSpace, class ShapeFunctionSetTuple >
387  template< class Functor >
389  ::doHessianEach ( int d, HessianRangeType hessian, std::size_t &index, const RangeFieldType *buffer, Functor functor ) const
390  {
391  if( d < dimension )
392  {
393  for( std::size_t i = 0; i < sizes_[ d ]; ++i )
394  {
395  HessianRangeType h( hessian );
396  h[ 0 ][ d ][ d ] *= buffer[ i + 2*sizes_[ d ] ];
397  for( int j = 1; j < dimension; ++j )
398  {
399  h[ 0 ][ (d+j)%dimension ][ d ] *= buffer[ i * sizes_[ d ] ];
400  h[ 0 ][ d ][ (d+j)%dimension ] *= buffer[ i * sizes_[ d ] ];
401  for( int k = 1; k < dimension; ++k )
402  h[ 0 ][ (d+j)%dimension ][ (d+k)%dimension ] *= buffer[ i ];
403  }
404  doHessianEach( d+1, h, index, buffer+3*sizes_[ d ], functor );
405  }
406  }
407  else
408  functor( index++, hessian );
409  }
410 
411  } // namespace Fem
412 
413 } // namespace Dune
414 
415 #endif // #ifndef DUNE_FEM_SHAPEFUNCTIONSET_TENSORPRODUCT_HH
int order() const
return order of shape functions
VectorSpaceTraits< DomainField, RangeField, dimD, dimR >::RangeFieldType RangeFieldType
Intrinsic type used for values in the range field (usually a double)
Definition: functionspaceinterface.hh:62
Definition: tensorproduct.hh:131
Assign(RangeFieldType *buffer)
Definition: tensorproduct.hh:102
void evaluateEach(const Point &x, Functor functor) const
Definition: tensorproduct.hh:303
void visit(const ShapeFunctionSet &shapeFunctionSet)
Definition: tensorproduct.hh:136
A vector valued function space.
Definition: functionspace.hh:16
FunctionSpaceType::DomainFieldType DomainFieldType
Definition: tensorproduct.hh:52
Order()
Definition: tensorproduct.hh:133
static constexpr T max(T a)
Definition: utility.hh:65
VectorSpaceTraits< DomainField, RangeField, dimD, dimR >::LinearMappingType JacobianRangeType
Intrinsic type used for the jacobian values has a Dune::FieldMatrix type interface.
Definition: functionspaceinterface.hh:74
std::size_t size() const
Definition: tensorproduct.hh:291
FieldVector< FieldMatrix< RangeFieldType, dimDomain, dimDomain >, dimRange > HessianRangeType
Intrinsic type used for the hessian values has a Dune::FieldMatrix type interface.
Definition: functionspaceinterface.hh:78
Definition: tensorproduct.hh:100
const ThisType & operator=(const ThisType &other)
Definition: tensorproduct.hh:261
Definition: shapefunctionset/shapefunctionset.hh:33
Definition: tensorproduct.hh:29
FunctionSpace FunctionSpaceType
Definition: tensorproduct.hh:49
dimension of domain vector space
Definition: functionspaceinterface.hh:45
FunctionSpaceType::RangeFieldType RangeFieldType
Definition: tensorproduct.hh:53
dimension of range vector space
Definition: functionspaceinterface.hh:47
ShapeFunctionSetTuple ShapeFunctionSetTupleType
Definition: tensorproduct.hh:50
FunctionSpaceType::RangeType RangeType
Definition: tensorproduct.hh:56
FunctionSpaceType::JacobianRangeType JacobianRangeType
Definition: tensorproduct.hh:57
VectorSpaceTraits< DomainField, RangeField, dimD, dimR >::DomainFieldType DomainFieldType
Intrinsic type used for values in the domain field (usually a double)
Definition: functionspaceinterface.hh:59
~TensorProductShapeFunctionSet()
Definition: tensorproduct.hh:237
Definition: coordinate.hh:4
VectorSpaceTraits< DomainField, RangeField, dimD, dimR >::DomainType DomainType
Type of domain vector (using type of domain field) has a Dune::FieldVector type interface.
Definition: functionspaceinterface.hh:66
FunctionSpaceType::HessianRangeType HessianRangeType
Definition: tensorproduct.hh:58
FunctionSpaceType::DomainType DomainType
Definition: tensorproduct.hh:55
void hessianEach(const Point &x, Functor functor) const
Definition: tensorproduct.hh:332
VectorSpaceTraits< DomainField, RangeField, dimD, dimR >::RangeType RangeType
Type of range vector (using type of range field) has a Dune::FieldVector type interface.
Definition: functionspaceinterface.hh:70
int order() const
Definition: tensorproduct.hh:280
static const Point & coordinate(const Point &x)
Definition: coordinate.hh:11
void jacobianEach(const Point &x, Functor functor) const
Definition: tensorproduct.hh:316