dune-fem  2.4.1-rc
space/fourier/functionset.hh
Go to the documentation of this file.
1 #ifndef DUNE_FEM_SPACE_FOURIER_FUNCTIONSET_HH
2 #define DUNE_FEM_SPACE_FOURIER_FUNCTIONSET_HH
3 
4 #include <cassert>
5 #include <cstddef>
6 #include <limits>
7 #include <array>
8 
9 #include <dune/common/fmatrix.hh>
10 #include <dune/common/fvector.hh>
11 #include <dune/common/power.hh>
12 
14 #include <dune/fem/version.hh>
15 
16 
17 namespace Dune
18 {
19 
20  namespace Fem
21  {
22 
23  // FourierFunctionSetSize
24  // ----------------------
25 
26  template< int dimension, int Order >
28  {
29  static const int v = StaticPower< (2*Order+1), dimension >::power;
30  };
31 
32 
33 
34  // FourierFunctionSet
35  // ------------------
36 
37  template< class FunctionSpace, int Order >
39 
40 
41 
42  // Template specialization for dimDomain = dimRange = 1
43  // ----------------------------------------------------
44 
45  template< class DomainFieldType, class RangeFieldType, int Order >
46  class FourierFunctionSet< FunctionSpace< DomainFieldType, RangeFieldType, 1, 1 >, Order >
47  {
49 
50  public:
52 
57 
58  typedef std::size_t SizeType;
59 
60  explicit FourierFunctionSet ( int order ) : order_( order ) {}
61 
62  int order () const { return order_; }
63 
64  static SizeType size () { return FourierFunctionSetSize< 1, Order >::v; }
65 
66  template< class Functor >
67  static void evaluateEach ( const DomainType &x, Functor functor )
68  {
69  functor( 0, RangeFieldType( 1 ) / RangeFieldType( 2 ) );
70  // use recursion:
71  // sin((n+1)*x) = sin(n*x)*cos(x) + cos(n*x)*sin(x)
72  // cos((n+1)*x) = cos(n*x)*cos(x) - sin(n*x)*sin(x)
73  SizeType basisFunction = 1;
74  for( int n = 1; n <= Order; ++n )
75  {
76  functor( basisFunction++, std::cos( n*x[ 0 ] ) );
77  functor( basisFunction++, std::sin( n*x[ 0 ] ) );
78  }
79  }
80 
81  template< class Functor >
82  static void jacobianEach ( const DomainType &x, Functor functor )
83  {
84  functor( 0, RangeFieldType( 0 ) );
85  SizeType basisFunction = 1;
86  for( int n = 1; n <= Order; ++n )
87  {
88  functor( basisFunction++, -n*std::sin( n*x[ 0 ] ) );
89  functor( basisFunction++, n*std::cos( n*x[ 0 ] ) );
90  }
91  }
92 
93  template< class Functor >
94  static void hessianEach ( const DomainType &x, Functor functor )
95  {
96  functor( 0, RangeFieldType( 0 ) );
97  SizeType basisFunction = 1;
98  for( int n = 1; n <= Order; ++n )
99  {
100  functor( basisFunction++, -(n*n)*std::cos( n*x[ 0 ] ) );
101  functor( basisFunction++, -(n*n)*std::sin( n*x[ 0 ] ) );
102  }
103  }
104  private:
105  int order_;
106  };
107 
108 
109 
110  // Template specialization for dimDomain > 1, dimRange = 1
111  // -------------------------------------------------------
112 
113  template< class DomainFieldType, class RangeFieldType, int dimDomain, int Order >
114  class FourierFunctionSet< FunctionSpace< DomainFieldType, RangeFieldType, dimDomain, 1 >, Order >
115  {
117 
118  public:
120 
125 
126  typedef std::size_t SizeType;
127 
128  private:
129  // number of Fourier basis function for dimDomain = 1
130  static const int buffer_size = FourierFunctionSetSize< 1, Order >::v;
131 
132  // tags used for building cache
133  struct Evaluate {}; //< evaluate basis functions
134  struct Jacobian {}; //< evaluate basis functions and jacobians
135  struct Hessian {}; //< evaluate basis functions, jacobians, and hessians
136 
137  struct Assign;
138 
139  protected:
140  // multi index used for tensor product basis functions
141  typedef Dune::FieldVector< int, dimDomain > MultiIndexType;
142 
143  // iterator type and methods for accessing multi indices
144  struct MultiIndexIterator;
145  typedef MultiIndexIterator IteratorType;
146  static IteratorType begin () { return IteratorType::begin(); }
147  static IteratorType end () { return IteratorType::end(); }
148 
149  public:
150  explicit FourierFunctionSet ( int order ) : order_( order ) {}
151 
152  int order () const { return order_; }
153 
155 
156  template< class Functor >
157  void evaluateEach ( const DomainType &x, Functor functor ) const
158  {
159  prepare( Evaluate(), x );
160  SizeType index( 0 );
161  const IteratorType end = ThisType::end();
162  for( IteratorType it = ThisType::begin(); it != end; ++it, ++index )
163  {
164  RangeType value;
165  evaluate( *it, value );
166  assert( index == IteratorType::index( *it ) );
167  functor( index, value );
168  }
169  assert( index == size() );
170  }
171 
172  template< class Functor >
173  void jacobianEach ( const DomainType &x, Functor functor ) const
174  {
175  prepare( Jacobian(), x );
176  SizeType index( 0 );
177  const IteratorType end = ThisType::end();
178  for( IteratorType it = ThisType::begin(); it != end; ++it, ++index )
179  {
180  JacobianRangeType jacobian;
181  evaluate( *it, jacobian );
182  assert( index == IteratorType::index( *it ) );
183  functor( index, jacobian );
184  }
185  assert( index == size() );
186  }
187 
188  template< class Functor >
189  void hessianEach ( const DomainType &x, Functor functor ) const
190  {
191  prepare( Hessian(), x );
192  SizeType index( 0 );
193  const IteratorType end = ThisType::end();
194  for( IteratorType it = ThisType::begin(); it != end; ++it, ++index )
195  {
196  HessianRangeType hessian;
197  evaluate( *it, hessian );
198  assert( index == IteratorType::index( *it ) );
199  functor( index, hessian );
200  }
201  assert( index == size() );
202  }
203 
204  protected:
205  // evaluate tensor product basis function
206  void evaluate ( const MultiIndexType &multiIndex, RangeType &value ) const
207  {
208  value = RangeType( RangeFieldType( 1 ) );
209  for( SizeType i = 0; i < dimDomain; ++i )
210  value *= buffer_[ i ][ multiIndex[ i ] ];
211  }
212 
213  // evaluate jacobian of tensor product basis function
214  void evaluate ( const MultiIndexType &multiIndex, JacobianRangeType &jacobian ) const
215  {
216  jacobian = JacobianRangeType( 1 );
217  for( int k = 0; k < dimDomain; ++k )
218  {
219  const RangeFieldType phi = buffer_[ k ][ multiIndex[ k ] ];
220  const RangeFieldType dphi = buffer_[ k ][ buffer_size + multiIndex[ k ] ];
221  for( int i = 0; i < dimDomain; ++i )
222  jacobian[ 0 ][ i ] *= (k == i ? dphi : phi);
223  }
224  }
225 
226  // evaluate hessian of tensor product basis function
227  void evaluate ( const MultiIndexType &multiIndex, HessianRangeType &hessian ) const
228  {
229  for( int i = 0; i < dimDomain; ++i )
230  for( int j = 0; j < dimDomain; ++j )
231  hessian[ 0 ][ i ][ j ] = RangeFieldType( 1 );
232 
233  for( int k = 0; k < dimDomain; ++k )
234  {
235  const RangeFieldType phi = buffer_[ k ][ multiIndex[ k ] ];
236  const RangeFieldType dphi = buffer_[ k ][ buffer_size + multiIndex[ k ] ];
237  for( int i = 0; i < dimDomain; ++i )
238  {
239  hessian[ 0 ][ i ][ i ] *= (k == i ? buffer_[ i ][ 2*buffer_size + multiIndex[ i ] ] : phi);
240  for( int j = i+1; j < dimDomain; ++j )
241  {
242  RangeFieldType tmp = ( k == i || k == j ) ? dphi : phi;
243  hessian[ 0 ][ i ][ j ] *= tmp;
244  hessian[ 0 ][ j ][ i ] *= tmp;
245  }
246  }
247  }
248  }
249 
250  // methods for building cache
251  void prepare ( const Evaluate &, const DomainType &x ) const;
252  void prepare ( const Jacobian &, const DomainType &x ) const;
253  void prepare ( const Hessian &, const DomainType &x ) const;
254 
255  private:
256  int order_;
257  // cache for evaluation of basis functions
258  mutable std::array< std::array< RangeFieldType, 3*buffer_size>, dimDomain > buffer_;
259  };
260 
261 
262 
263  // Implementation of FourierFunctionSet::Assign
264  // --------------------------------------------
265 
266  template< class DomainFieldType, class RangeFieldType, int dimDomain, int Order >
267  struct FourierFunctionSet< FunctionSpace< DomainFieldType, RangeFieldType, dimDomain, 1 >, Order >::Assign
268  {
269  explicit Assign ( RangeFieldType *buffer ) : buffer_( buffer ) {}
270 
271  void operator() ( const std::size_t i, const RangeFieldType &value )
272  {
273  buffer_[ i ] = value;
274  }
275 
276  template< class T >
277  void operator() ( const std::size_t i, const FieldVector< T, 1 > &value )
278  {
279  (*this)( i, value[ 0 ] );
280  }
281 
282  template< class T >
283  void operator() ( const std::size_t i, const FieldMatrix< T, 1, 1 > &value )
284  {
285  (*this)( i, value[ 0 ][ 0 ] );
286  }
287 
288  private:
289  RangeFieldType *buffer_;
290  };
291 
292 
293 
294  // Implementation of FourierFunctionSet::MultiIndexIterator
295  // --------------------------------------------------------
296 
297  template< class DomainFieldType, class RangeFieldType, int dimDomain, int Order >
298  struct FourierFunctionSet< FunctionSpace< DomainFieldType, RangeFieldType, dimDomain, 1 >, Order >::MultiIndexIterator
299  {
300  typedef MultiIndexIterator ThisType;
301 
302  protected:
303  typedef int IndexType;
304 
305  explicit MultiIndexIterator ( IndexType n ) : multiIndex_( n ) {}
306 
307  static IndexType invalidIndex () { return std::numeric_limits< IndexType >::max(); }
308 
310 
311  public:
312  static ThisType begin () { return ThisType( 0 ); }
313  static ThisType end () { return ThisType( invalidIndex() ); }
314 
315  ThisType operator++ ()
316  {
317  // try to increment and leave eventually
318  for( int i = 0; i < dimDomain; ++i )
319  {
320  const int j = dimDomain-i-1;
321  if( ++multiIndex_[ j ] < N )
322  return *this;
323  multiIndex_[ j ] = 0;
324  }
325 
326  // otherwise, reset this iterator to end iterator
327  *this = end();
328  return *this;
329  }
330 
331  bool operator== ( const ThisType &other ) const { return ( multiIndex_ == other.multiIndex_ ); }
332 
333  bool operator!= ( const ThisType &other ) const { return !( *this == other ); }
334 
335  const MultiIndexType &operator* () const { return multiIndex_; }
336 
337  const MultiIndexType *operator-> () const { return &multiIndex_; }
338 
339  SizeType index () const { return index( multiIndex_ ); }
340 
341  static SizeType index ( const MultiIndexType &multiIndex )
342  {
343  SizeType index = 0, factor = 1;
344  for( int i = dimDomain-1; i >= 0; --i )
345  {
346  index += multiIndex[ i ]*factor;
347  factor *= N;
348  }
349  assert( index < size() );
350  return index;
351  }
352 
353  private:
354  MultiIndexType multiIndex_;
355  };
356 
357 
358 
359  // Implementation of FourierFunctionSet
360  // ------------------------------------
361 
362  template< class DomainFieldType, class RangeFieldType, int dimDomain, int Order >
364  ::prepare ( const Evaluate &, const DomainType &x ) const
365  {
367  for( SizeType i = 0; i < dimDomain; ++i )
368  {
369  RangeFieldType *it = &buffer_[ i ][ 0 ];
370  Dune::FieldVector< DomainFieldType, 1 > y( x[ i ] );
371  FunctionSetImp::evaluateEach( y, Assign( it ) );
372  }
373  };
374 
375 
376  template< class DomainFieldType, class RangeFieldType, int dimDomain, int Order >
377  void FourierFunctionSet< FunctionSpace< DomainFieldType, RangeFieldType, dimDomain, 1 >, Order >
378  ::prepare ( const Jacobian &, const DomainType &x ) const
379  {
381  for( SizeType i = 0; i < dimDomain; ++i )
382  {
383  RangeFieldType *it = &buffer_[ i ][ 0 ];
384  Dune::FieldVector< DomainFieldType, 1 > y( x[ i ] );
385  FunctionSetImp::evaluateEach( y, Assign( it ) );
386  FunctionSetImp::jacobianEach( y, Assign( it+buffer_size ) );
387  }
388  };
389 
390 
391  template< class DomainFieldType, class RangeFieldType, int dimDomain, int Order >
392  void FourierFunctionSet< FunctionSpace< DomainFieldType, RangeFieldType, dimDomain, 1 >, Order >
393  ::prepare ( const Hessian &, const DomainType &x ) const
394  {
396  for( SizeType i = 0; i < dimDomain; ++i )
397  {
398  RangeFieldType *it = &buffer_[ i ][ 0 ];
399  Dune::FieldVector< DomainFieldType, 1 > y( x[ i ] );
400  FunctionSetImp::evaluateEach( y, Assign( it ) );
401  FunctionSetImp::jacobianEach( y, Assign( it+buffer_size) );
402  FunctionSetImp::hessianEach( y, Assign( it+2*buffer_size ) );
403  }
404  };
405 
406  } // namespace Fem
407 
408 } // namespace Dune
409 
410 #endif // #ifndef DUNE_FEM_SPACE_FOURIER_FUNCTIONSET_HH
static void jacobianEach(const DomainType &x, Functor functor)
Definition: space/fourier/functionset.hh:82
FunctionSpaceType::JacobianRangeType JacobianRangeType
Definition: space/fourier/functionset.hh:55
FunctionSpaceType::RangeType RangeType
Definition: space/fourier/functionset.hh:54
A vector valued function space.
Definition: functionspace.hh:16
static double sin(const Double &v)
Definition: double.hh:875
FunctionSpaceType::DomainType DomainType
Definition: space/fourier/functionset.hh:53
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
FieldVector< FieldMatrix< RangeFieldType, dimDomain, dimDomain >, dimRange > HessianRangeType
Intrinsic type used for the hessian values has a Dune::FieldMatrix type interface.
Definition: functionspaceinterface.hh:78
FunctionSpaceType::HessianRangeType HessianRangeType
Definition: space/fourier/functionset.hh:56
FunctionSpace< DomainFieldType, RangeFieldType, dimDomain, 1 > FunctionSpaceType
Definition: space/fourier/functionset.hh:119
void jacobianEach(const DomainType &x, Functor functor) const
Definition: space/fourier/functionset.hh:173
Definition: space/fourier/functionset.hh:38
bool operator!=(const Double &a, const Double &b)
Definition: double.hh:629
static const int v
Definition: space/fourier/functionset.hh:29
bool operator==(const Double &a, const Double &b)
Definition: double.hh:589
Definition: coordinate.hh:4
Definition: space/fourier/functionset.hh:27
static double cos(const Double &v)
Definition: double.hh:880
static SizeType index(const MultiIndexType &multiIndex)
Definition: space/fourier/functionset.hh:341
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
FunctionSpace< DomainFieldType, RangeFieldType, 1, 1 > FunctionSpaceType
Definition: space/fourier/functionset.hh:51
void hessianEach(const DomainType &x, Functor functor) const
Definition: space/fourier/functionset.hh:189
Dune::FieldVector< int, dimDomain > MultiIndexType
Definition: space/fourier/functionset.hh:137
void evaluate(const MultiIndexType &multiIndex, HessianRangeType &hessian) const
Definition: space/fourier/functionset.hh:227
Double operator*(const Double &a, const Double &b)
Definition: double.hh:495
FunctionSpaceType::RangeType RangeType
Definition: space/fourier/functionset.hh:122
void evaluateEach(const DomainType &x, Functor functor) const
Definition: space/fourier/functionset.hh:157
static void evaluateEach(const DomainType &x, Functor functor)
Definition: space/fourier/functionset.hh:67
void evaluate(const MultiIndexType &multiIndex, JacobianRangeType &jacobian) const
Definition: space/fourier/functionset.hh:214
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
FunctionSpaceType::HessianRangeType HessianRangeType
Definition: space/fourier/functionset.hh:124
FunctionSpaceType::DomainType DomainType
Definition: space/fourier/functionset.hh:121
FunctionSpaceType::JacobianRangeType JacobianRangeType
Definition: space/fourier/functionset.hh:123
void evaluate(const MultiIndexType &multiIndex, RangeType &value) const
Definition: space/fourier/functionset.hh:206
static void hessianEach(const DomainType &x, Functor functor)
Definition: space/fourier/functionset.hh:94