Dune Core Modules (unstable)

polynomialbasis.hh
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
12
13#include <dune/localfunctions/common/localbasis.hh>
14
15#include <dune/localfunctions/utility/coeffmatrix.hh>
16#include <dune/localfunctions/utility/monomialbasis.hh>
17#include <dune/localfunctions/utility/multiindex.hh>
18#include <dune/localfunctions/utility/basisevaluator.hh>
19
20namespace 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>,
77 typedef typename Evaluator::Basis Basis;
78 typedef typename Evaluator::DomainVector DomainVector;
79 template <class Fy>
82
83 PolynomialBasis (const Basis &basis,
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());
218 const DomainVector &bx = Convert<true,DVector>::apply(x);
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:
322 PolynomialBasis(const PolynomialBasis &other)
323 : basis_(other.basis_),
324 coeffMatrix_(other.coeffMatrix_),
325 eval_(basis_),
326 order_(basis_.order()),
327 size_(other.size_)
328 {}
329 PolynomialBasis &operator=(const PolynomialBasis&);
330 const Basis &basis_;
331 const CoefficientMatrix* coeffMatrix_;
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
359 PolynomialBasisWithMatrix (const Basis &basis)
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
A dense n x m matrix.
Definition: fmatrix.hh:117
vector space out of a tensor product of fields.
Definition: fvector.hh:92
A generic dynamic dense matrix.
Definition: matrix.hh:561
Default exception for dummy implementations.
Definition: exceptions.hh:355
Definition: polynomialbasis.hh:346
Definition: polynomialbasis.hh:63
void evaluateHessian(const typename Traits::DomainType &x, std::vector< HessianType > &out) const
Evaluate Jacobian of all shape functions.
Definition: polynomialbasis.hh:133
void evaluateFunction(const typename Traits::DomainType &x, std::vector< typename Traits::RangeType > &out) const
Evaluate all shape functions.
Definition: polynomialbasis.hh:117
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 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
Implements a matrix constructed from a given type representing a field and compile-time given number ...
#define DUNE_THROW(E,...)
Definition: exceptions.hh:312
constexpr T accumulate(Range &&range, T value, F &&f)
Accumulate values.
Definition: hybridutilities.hh:280
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:159
Type traits for LocalBasisVirtualInterface.
Definition: localbasis.hh:35
D DomainType
domain type
Definition: localbasis.hh:43
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden & Uni Heidelberg  |  generated with Hugo v0.111.3 (Mar 12, 23:28, 2025)