dune-localfunctions  2.11
polynomialbasis.hh
Go to the documentation of this file.
1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 // SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
4 // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
5 #ifndef DUNE_POLYNOMIALBASIS_HH
6 #define DUNE_POLYNOMIALBASIS_HH
7 
8 #include <fstream>
9 #include <numeric>
10 
11 #include <dune/common/fmatrix.hh>
12 
14 
19 
20 namespace Dune
21 {
22 
23  // PolynomialBasis
24  // ---------------
25 
61  template< class Eval, class CM, class D, class R >
63  {
64  typedef PolynomialBasis This;
65  typedef Eval Evaluator;
66 
67  public:
68  typedef CM CoefficientMatrix;
69 
70  typedef typename CoefficientMatrix::Field StorageField;
71 
72  static const unsigned int dimension = Evaluator::dimension;
73  static const unsigned int dimRange = Evaluator::dimRange*CoefficientMatrix::blockSize;
75  R,dimRange,FieldVector<R,dimRange>,
76  FieldMatrix<R,dimRange,dimension> > Traits;
77  typedef typename Evaluator::Basis Basis;
78  typedef typename Evaluator::DomainVector DomainVector;
79  template <class Fy>
80  using HessianFyType = FieldVector<FieldMatrix<Fy,dimension,dimension>,dimRange>;
82 
84  const CoefficientMatrix &coeffMatrix,
85  unsigned int size)
86  : basis_(basis),
87  coeffMatrix_(&coeffMatrix),
88  eval_(basis),
89  order_(basis.order()),
90  size_(size)
91  {
92  // assert(coeffMatrix_);
93  // assert(size_ <= coeffMatrix.size()); // !!!
94  }
95 
96  const Basis &basis () const
97  {
98  return basis_;
99  }
100 
101  const CoefficientMatrix &matrix () const
102  {
103  return *coeffMatrix_;
104  }
105 
106  unsigned int order () const
107  {
108  return order_;
109  }
110 
111  unsigned int size () const
112  {
113  return size_;
114  }
115 
117  void evaluateFunction (const typename Traits::DomainType& x,
118  std::vector<typename Traits::RangeType>& out) const
119  {
120  out.resize(size());
121  evaluate(x,out);
122  }
123 
125  void evaluateJacobian (const typename Traits::DomainType& x, // position
126  std::vector<typename Traits::JacobianType>& out) const // return value
127  {
128  out.resize(size());
129  jacobian(x,out);
130  }
131 
133  void evaluateHessian (const typename Traits::DomainType& x, // position
134  std::vector<HessianType>& out) const // return value
135  {
136  out.resize(size());
137  hessian(x,out);
138  }
139 
141  void partial (const std::array<unsigned int, dimension>& order,
142  const typename Traits::DomainType& in, // position
143  std::vector<typename Traits::RangeType>& out) const // return value
144  {
145  out.resize(size());
146  auto totalOrder = std::accumulate(order.begin(), order.end(), 0);
147  if (totalOrder == 0) {
148  evaluateFunction(in, out);
149  }
150  else if (totalOrder == 1) {
151  std::vector<typename Traits::JacobianType> jacs(out.size());
152  unsigned int k;
153  for (unsigned int i=0;i<order.size();++i)
154  if (order[i]==1) k=i;
155  evaluateJacobian(in, jacs);
156  for (unsigned int i=0;i<out.size();++i)
157  for (unsigned int r=0;r<Traits::RangeType::dimension;++r)
158  out[i][r] = jacs[i][r][k];
159  }
160  else if (totalOrder == 2) {
161  std::vector<HessianType> hesss(out.size());
162  int k=-1,l=-1;
163  for (unsigned int i=0;i<order.size();++i) {
164  if (order[i] >= 1 && k == -1)
165  k = i;
166  else if (order[i]==1) l=i;
167  }
168  if (l==-1) l=k;
169  evaluateHessian(in, hesss);
170  for (unsigned int i=0;i<out.size();++i)
171  for (unsigned int r=0;r<Traits::RangeType::dimension;++r)
172  out[i][r] = hesss[i][r][k][l];
173  }
174  else {
175  DUNE_THROW(NotImplemented, "Desired derivative order is not implemented");
176  }
177  }
178 
179  template< unsigned int deriv, class F >
180  void evaluate ( const DomainVector &x, F *values ) const
181  {
182  coeffMatrix_->mult( eval_.template evaluate<deriv>( x ), size(), values);
183  }
184  template< unsigned int deriv, class DVector, class F >
185  void evaluate ( const DVector &x, F *values ) const
186  {
187  assert( DVector::dimension == dimension);
188  DomainVector bx;
189  for( int d = 0; d < dimension; ++d )
190  field_cast( x[ d ], bx[ d ] );
191  evaluate<deriv>( bx, values );
192  }
193 
194  template <bool dummy,class DVector>
195  struct Convert
196  {
197  static DomainVector apply( const DVector &x )
198  {
199  assert( DVector::dimension == dimension);
200  DomainVector bx;
201  for( unsigned int d = 0; d < dimension; ++d )
202  field_cast( x[ d ], bx[ d ] );
203  return bx;
204  }
205  };
206  template <bool dummy>
207  struct Convert<dummy,DomainVector>
208  {
209  static const DomainVector &apply( const DomainVector &x )
210  {
211  return x;
212  }
213  };
214  template< unsigned int deriv, class DVector, class RVector >
215  void evaluate ( const DVector &x, RVector &values ) const
216  {
217  assert(values.size()>=size());
219  coeffMatrix_->mult( eval_.template evaluate<deriv>( bx ), values );
220  }
221 
222  template <class Fy>
223  void evaluate ( const DomainVector &x, std::vector<FieldVector<Fy,dimRange> > &values ) const
224  {
225  evaluate<0>(x,values);
226  }
227  template< class DVector, class RVector >
228  void evaluate ( const DVector &x, RVector &values ) const
229  {
230  assert( DVector::dimension == dimension);
231  DomainVector bx;
232  for( unsigned int d = 0; d < dimension; ++d )
233  field_cast( x[ d ], bx[ d ] );
234  evaluate<0>( bx, values );
235  }
236 
237  template< unsigned int deriv, class Vector >
238  void evaluateSingle ( const DomainVector &x, Vector &values ) const
239  {
240  assert(values.size()>=size());
241  coeffMatrix_->template mult<deriv>( eval_.template evaluate<deriv>( x ), values );
242  }
243  template< unsigned int deriv, class Fy >
244  void evaluateSingle ( const DomainVector &x,
245  std::vector< FieldVector<FieldVector<Fy,LFETensor<Fy,dimension,deriv>::size>,dimRange> > &values) const
246  {
247  evaluateSingle<deriv>(x,reinterpret_cast<std::vector< FieldVector<Fy,LFETensor<Fy,dimension,deriv>::size*dimRange> >&>(values));
248  }
249  template< unsigned int deriv, class Fy >
250  void evaluateSingle ( const DomainVector &x,
251  std::vector< FieldVector<LFETensor<Fy,dimension,deriv>,dimRange> > &values) const
252  {
253  evaluateSingle<deriv>(x,reinterpret_cast<std::vector< FieldVector<Fy,LFETensor<Fy,dimension,deriv>::size*dimRange> >&>(values));
254  }
255 
256  template <class Fy>
257  void jacobian ( const DomainVector &x,
258  std::vector<FieldMatrix<Fy,dimRange,dimension> > &values ) const
259  {
260  assert(values.size()>=size());
261  evaluateSingle<1>(x,reinterpret_cast<std::vector<FieldVector<Fy,dimRange*dimension> >&>(values));
262  }
263  template< class DVector, class RVector >
264  void jacobian ( const DVector &x, RVector &values ) const
265  {
266  assert( DVector::dimension == dimension);
267  DomainVector bx;
268  for( unsigned int d = 0; d < dimension; ++d )
269  field_cast( x[ d ], bx[ d ] );
270  jacobian( bx, values );
271  }
272  template <class Fy>
273  void hessian ( const DomainVector &x,
274  std::vector<HessianFyType<Fy>> &values ) const
275  {
276  assert(values.size()>=size());
277  // only upper part of hessians matrix is computed - so we have
278  // y[0] = FV< FV<Fy,d*(d+1)/2>, dimRange>
279  const unsigned int hsize = LFETensor<Fy,dimension,2>::size;
280  std::vector< FieldVector< FieldVector<Fy,hsize>, dimRange> > y( size() );
281  evaluateSingle<2>(x, y);
282  unsigned int q = 0;
283  for (unsigned int i = 0; i < size(); ++i)
284  for (unsigned int r = 0; r < dimRange; ++r)
285  {
286  q = 0;
287  // tensor-based things follow unintuitive index scheme
288  // e.g. for dim = 3, the k-l index of y is 00,01,11,02,12,22, i.e. partial derivatives
289  // are ordered: xx,xy,yy,xz,yz,zz
290 
291  // Fill values 'directionwise'
292  for (unsigned int k = 0; k < dimension; ++k)
293  for (unsigned int l = 0; l <= k; ++l)
294  {
295 
296  values[i][r][k][l] = y[i][r][q];
297  values[i][r][l][k] = y[i][r][q];
298  assert(q < hsize);
299  ++q;
300  }
301  }
302  // evaluateSingle<2>(x,reinterpret_cast<std::vector<FieldVector<Fy,dimRange*dimension*dimension> >&>(values));
303  }
304  template< class DVector, class HVector >
305  void hessian ( const DVector &x, HVector &values ) const
306  {
307  assert( DVector::dimension == dimension);
308  DomainVector bx;
309  for( unsigned int d = 0; d < dimension; ++d )
310  field_cast( x[ d ], bx[ d ] );
311  hessian( bx, values );
312  }
313 
314  template <class Fy>
315  void integrate ( std::vector<Fy> &values ) const
316  {
317  assert(values.size()>=size());
318  coeffMatrix_->mult( eval_.integrate(), values );
319  }
320 
321  protected:
323  : basis_(other.basis_),
324  coeffMatrix_(other.coeffMatrix_),
325  eval_(basis_),
326  order_(basis_.order()),
327  size_(other.size_)
328  {}
330  const Basis &basis_;
332  mutable Evaluator eval_;
333  unsigned int order_,size_;
334  };
335 
342  template< class Eval, class CM = SparseCoeffMatrix<typename Eval::Field,Eval::dimRange>,
343  class D=double, class R=double>
345  : public PolynomialBasis< Eval, CM, D, R >
346  {
347  public:
348  typedef CM CoefficientMatrix;
349 
350  private:
351  typedef Eval Evaluator;
352 
355 
356  public:
357  typedef typename Base::Basis Basis;
358 
360  : Base(basis,coeffMatrix_,0)
361  {}
362 
363  template <class Matrix>
364  void fill(const Matrix& matrix)
365  {
366  coeffMatrix_.fill(matrix);
367  this->size_ = coeffMatrix_.size();
368  }
369  template <class Matrix>
370  void fill(const Matrix& matrix,int size)
371  {
372  coeffMatrix_.fill(matrix);
373  assert(size<=coeffMatrix_.size());
374  this->size_ = size;
375  }
376 
377  private:
380  CoefficientMatrix coeffMatrix_;
381  };
382 }
383 #endif // DUNE_POLYNOMIALBASIS_HH
void jacobian(const DVector &x, RVector &values) const
Definition: polynomialbasis.hh:264
void evaluate(const DomainVector &x, F *values) const
Definition: polynomialbasis.hh:180
void evaluateSingle(const DomainVector &x, std::vector< FieldVector< FieldVector< Fy, LFETensor< Fy, dimension, deriv >::size >, dimRange > > &values) const
Definition: polynomialbasis.hh:244
Definition: polynomialbasis.hh:62
Evaluator eval_
Definition: polynomialbasis.hh:332
Definition: polynomialbasis.hh:344
const Basis & basis_
Definition: polynomialbasis.hh:330
void evaluate(const DVector &x, F *values) const
Definition: polynomialbasis.hh:185
void integrate(std::vector< Fy > &values) const
Definition: polynomialbasis.hh:315
static const DomainVector & apply(const DomainVector &x)
Definition: polynomialbasis.hh:209
void evaluateSingle(const DomainVector &x, Vector &values) const
Definition: polynomialbasis.hh:238
const Basis & basis() const
Definition: polynomialbasis.hh:96
Base::Basis Basis
Definition: polynomialbasis.hh:357
Definition: bdfmcube.hh:17
static const unsigned int dimension
Definition: polynomialbasis.hh:72
const CoefficientMatrix & matrix() const
Definition: polynomialbasis.hh:101
static DomainVector apply(const DVector &x)
Definition: polynomialbasis.hh:197
CM CoefficientMatrix
Definition: polynomialbasis.hh:68
void evaluateSingle(const DomainVector &x, std::vector< FieldVector< LFETensor< Fy, dimension, deriv >, dimRange > > &values) const
Definition: polynomialbasis.hh:250
D DomainType
domain type
Definition: common/localbasis.hh:43
Definition: polynomialbasis.hh:195
void evaluateJacobian(const typename Traits::DomainType &x, std::vector< typename Traits::JacobianType > &out) const
Evaluate Jacobian of all shape functions.
Definition: polynomialbasis.hh:125
void fill(const Matrix &matrix)
Definition: polynomialbasis.hh:364
void fill(const Matrix &matrix, int size)
Definition: polynomialbasis.hh:370
HessianFyType< R > HessianType
Definition: polynomialbasis.hh:81
PolynomialBasis & operator=(const PolynomialBasis &)
const CoefficientMatrix * coeffMatrix_
Definition: polynomialbasis.hh:331
void jacobian(const DomainVector &x, std::vector< FieldMatrix< Fy, dimRange, dimension > > &values) const
Definition: polynomialbasis.hh:257
PolynomialBasisWithMatrix(const Basis &basis)
Definition: polynomialbasis.hh:359
void hessian(const DomainVector &x, std::vector< HessianFyType< Fy >> &values) const
Definition: polynomialbasis.hh:273
PolynomialBasis(const PolynomialBasis &other)
Definition: polynomialbasis.hh:322
LocalBasisTraits< D, dimension, FieldVector< D, dimension >, R, dimRange, FieldVector< R, dimRange >, FieldMatrix< R, dimRange, dimension > > Traits
Definition: polynomialbasis.hh:76
unsigned int order() const
Definition: polynomialbasis.hh:106
unsigned int size() const
Definition: polynomialbasis.hh:111
void hessian(const DVector &x, HVector &values) const
Definition: polynomialbasis.hh:305
void evaluateHessian(const typename Traits::DomainType &x, std::vector< HessianType > &out) const
Evaluate Jacobian of all shape functions.
Definition: polynomialbasis.hh:133
CM CoefficientMatrix
Definition: polynomialbasis.hh:348
unsigned int size_
Definition: polynomialbasis.hh:333
void evaluate(const DVector &x, RVector &values) const
Definition: polynomialbasis.hh:228
void partial(const std::array< unsigned int, dimension > &order, const typename Traits::DomainType &in, std::vector< typename Traits::RangeType > &out) const
Evaluate partial derivatives of all shape functions.
Definition: polynomialbasis.hh:141
CoefficientMatrix::Field StorageField
Definition: polynomialbasis.hh:70
Evaluator::Basis Basis
Definition: polynomialbasis.hh:77
Evaluator::DomainVector DomainVector
Definition: polynomialbasis.hh:78
unsigned int order_
Definition: polynomialbasis.hh:333
static const unsigned int dimRange
Definition: polynomialbasis.hh:73
PolynomialBasis(const Basis &basis, const CoefficientMatrix &coeffMatrix, unsigned int size)
Definition: polynomialbasis.hh:83
void evaluate(const DVector &x, RVector &values) const
Definition: polynomialbasis.hh:215
void evaluateFunction(const typename Traits::DomainType &x, std::vector< typename Traits::RangeType > &out) const
Evaluate all shape functions.
Definition: polynomialbasis.hh:117
Type traits for LocalBasisVirtualInterface.
Definition: common/localbasis.hh:34
void field_cast(const F1 &f1, F2 &f2)
a helper class to cast from one field to another
Definition: field.hh:160
Definition: tensor.hh:32
FieldVector< FieldMatrix< Fy, dimension, dimension >, dimRange > HessianFyType
Definition: polynomialbasis.hh:80
void evaluate(const DomainVector &x, std::vector< FieldVector< Fy, dimRange > > &values) const
Definition: polynomialbasis.hh:223