1 #ifndef DUNE_FEM_FUNCTION_LOCALFUNCTION_LOCALFUNCTION_HH
2 #define DUNE_FEM_FUNCTION_LOCALFUNCTION_LOCALFUNCTION_HH
3 
4 #include <utility>
5 #include <type_traits>
6 #include <tuple>
7 
8 #include <dune/common/deprecated.hh>
9 #include <dune/common/fvector.hh>
10 
11 
12 namespace Dune
13 {
14   namespace Fem {
15     // forward declaration for DenseMatVecTraits
16     template< class BasisFunctionSet, class LocalDofVector >
17     class LocalFunction;
18   }
19 
20 
21   // DenseMatVecTraits for LocalFunction for Discrete Functions
22   // ----------------------------------------------------------
23 
24   template< class BasisFunctionSet, class LocalDofVector >
25   struct DenseMatVecTraits< Fem::LocalFunction< BasisFunctionSet, LocalDofVector > >
26   {
27     typedef Fem::LocalFunction< BasisFunctionSet, LocalDofVector >  derived_type;
28     typedef typename LocalDofVector::value_type                     value_type;
29     //typedef LocalDofVector                                          container_type;
30     typedef typename LocalDofVector::size_type                      size_type;
31   };
32 
33 
34 
35   // FieldTraits for LocalContribution for Discrete Functions
36   // --------------------------------------------------------
37 
38   template< class BasisFunctionSet, class LocalDofVector >
39   struct FieldTraits< Fem::LocalFunction< BasisFunctionSet, LocalDofVector > >
40   {
41     typedef typename FieldTraits< typename LocalDofVector::value_type >::field_type field_type;
42     typedef typename FieldTraits< typename LocalDofVector::value_type >::real_type  real_type;
43   };
44 
45 
46   namespace Fem
47   {
48 
49     /** \addtogroup LocalFunction
50      *
51      * On every element from a discrete function the local funtion can be
52      * accessed. With the local function one has access to the dof and on the
53      * other hand to the basis function set of this actual element. Therefore
54      * this is called a local function.
55      *
56      * \remarks The interface for using a LocalFunction is defined by the class
57      *          LocalFunction.
58      *
59      * \{
60      */
61 
62 
63 
64     // LocalFunction
65     // -------------
66 
67     /** \class LocalFunction
68      *  \brief interface for local functions
69      *
70      *  Local functions are used to represend a discrete function on one entity.
71      *  The LocalFunctionInterface defines the functionality that can be expected
72      *  from such a local function.
73      */
74     template< class BasisFunctionSet, class LocalDofVector >
75     class LocalFunction
76       : public Dune::DenseVector< LocalFunction< BasisFunctionSet, LocalDofVector > >
77     {
78       typedef LocalFunction< BasisFunctionSet, LocalDofVector > ThisType;
79       typedef Dune::DenseVector< ThisType > BaseType;
80     public:
81 
82       //! type of basis function set
83       typedef BasisFunctionSet BasisFunctionSetType;
84 
85       /** \brief  type of local Dof Vector  */
86       typedef LocalDofVector LocalDofVectorType;
87 
88       //! type of DoF use with the discrete function
89       typedef typename LocalDofVectorType::value_type DofType;
90 
91       //! type of index
92       typedef typename LocalDofVectorType::size_type SizeType;
93 
94       //! type of the entity, the local function lives on is given by the space
95       typedef typename BasisFunctionSetType::EntityType EntityType;
96 
97       //! type of functionspace
98       typedef typename BasisFunctionSetType::FunctionSpaceType FunctionSpaceType;
99 
100       //! field type of the domain
101       typedef typename FunctionSpaceType::DomainFieldType DomainFieldType;
102       //! field type of the range
103       typedef typename FunctionSpaceType::RangeFieldType RangeFieldType;
104       //! type of domain vectors, i.e., type of coordinates
105       typedef typename FunctionSpaceType::DomainType DomainType;
106       //! type of range vectors, i.e., type of function values
107       typedef typename FunctionSpaceType::RangeType RangeType;
108       //! type of the Jacobian, i.e., type of evaluated Jacobian matrix
109       typedef typename FunctionSpaceType::JacobianRangeType JacobianRangeType;
110       //! type of the Hessian
111       typedef typename FunctionSpaceType::HessianRangeType HessianRangeType;
112 
113       //! type of local coordinates
114       typedef typename EntityType::Geometry::LocalCoordinate LocalCoordinateType;
115 
116       //! dimension of the domain
117       static const int dimDomain = FunctionSpaceType::dimDomain;
118       //! dimension of the range
119       static const int dimRange = FunctionSpaceType::dimRange;
120 
121       //! default constructor, calls default ctor of BasisFunctionSetType and LocalDofVectorType
LocalFunction()122       LocalFunction () {}
123 
124       //! ctor taking a basisFunctionSet, calling default ctor for LocalDofVectorType, and resize
LocalFunction(const BasisFunctionSetType & basisFunctionSet)125       explicit LocalFunction ( const BasisFunctionSetType &basisFunctionSet )
126       : basisFunctionSet_( basisFunctionSet )
127       {
128         localDofVector_.resize( basisFunctionSet.size() );
129       }
130 
131       //! ctor taking a localDofVector, calling default ctor for BasisFunctionSetType
LocalFunction(const LocalDofVectorType & localDofVector)132       explicit LocalFunction ( const LocalDofVectorType &localDofVector ) : localDofVector_( localDofVector ) {}
133 
134       //! copy given agruments
LocalFunction(const BasisFunctionSetType & basisFunctionSet,const LocalDofVector & localDofVector)135       LocalFunction ( const BasisFunctionSetType &basisFunctionSet, const LocalDofVector &localDofVector )
136       : basisFunctionSet_( basisFunctionSet ),
137         localDofVector_( localDofVector )
138       {
139         localDofVector_.resize( basisFunctionSet.size() );
140       }
141 
142       //! half move ctor
LocalFunction(LocalDofVectorType && localDofVector)143       explicit LocalFunction ( LocalDofVectorType &&localDofVector ) : localDofVector_( localDofVector ) {}
144 
145       //! half move ctor
LocalFunction(const BasisFunctionSetType & basisFunctionSet,LocalDofVector && localDofVector)146       LocalFunction ( const BasisFunctionSetType &basisFunctionSet, LocalDofVector &&localDofVector )
147       : basisFunctionSet_( basisFunctionSet ),
148         localDofVector_( localDofVector )
149       {
150         localDofVector_.resize( basisFunctionSet.size() );
151       }
152 
153       //! move constructor
LocalFunction(ThisType && other)154       LocalFunction ( ThisType && other )
155       : basisFunctionSet_( std::move( other.basisFunctionSet_ ) ),
156         localDofVector_( std::move( other.localDofVector_ ) )
157       {}
158 
159       //! copy constructor
LocalFunction(const ThisType & other)160       LocalFunction ( const ThisType & other )
161       : basisFunctionSet_( other.basisFunctionSet_ ),
162         localDofVector_( other.localDofVector_ )
163       {}
164 
165       /** \brief access to local dofs (read-only)
166        *
167        *  \param[in]  num  local dof number
168        *  \return reference to dof
169        */
operator [](SizeType num) const170       const DofType &operator[] ( SizeType num ) const { return localDofVector_[ num ]; }
171 
172       /** \brief access to local dofs (read-write)
173        *
174        *  \param[in]  num  local DoF number
175        *  \return reference to DoF
176        */
operator [](SizeType num)177       DofType &operator[] ( SizeType num ) { return localDofVector_[ num ]; }
178 
179       using BaseType :: operator +=;
180       using BaseType :: operator -=;
181       using BaseType :: operator *=;
182       using BaseType :: operator /=;
183 
184       /** \brief assign all DoFs of this local function
185        *
186        *  \param[in]  lf  local function to assign DoFs from
187        */
188       template< class T >
assign(const LocalFunction<BasisFunctionSet,T> & other)189       void assign ( const LocalFunction< BasisFunctionSet, T > &other )
190       {
191         localDofVector() = other.localDofVector();
192       }
193 
194       /** \brief set all DoFs to zero */
clear()195       void clear ()
196       {
197         std::fill( localDofVector().begin(), localDofVector().end(), DofType( 0 ) );
198       }
199 
200 #if 0
201       /** \brief add a multiple of another local function to this one
202        *
203        *  \note The local function to add may be any implementation of a
204        *        LocalFunction.
205        *
206        *  \param[in]  s   scalar factor to scale lf with
207        *  \param[in]  lf  local function to add
208        *
209        *  \returns a reference to this local function (i.e., *this)
210        */
211       template< class T >
212       ThisType &axpy ( const RangeFieldType s, const LocalFunction< BasisFunctionSet, T > &other )
213       {
214         localDofVector().axpy( s, other.localDofVector() );
215         return *this;
216       }
217 #endif
218       using BaseType :: axpy;
219 
220       /** \brief axpy operation for local function
221        *
222        *  Denoting the DoFs of the local function by \f$u_i\f$ and the basis
223        *  functions by \f$\varphi_i\f$, this function performs the following
224        *  operation:
225        *  \f[
226        *  u_i = u_i + factor \cdot \varphi_i( x )
227        *  \f]
228        *
229        *  \param[in]  x       point to evaluate basis functions in
230        *  \param[in]  factor  axpy factor
231        */
232       template< class PointType >
axpy(const PointType & x,const RangeType & factor)233       void axpy ( const PointType &x, const RangeType &factor )
234       {
235         basisFunctionSet().axpy( x, factor, localDofVector() );
236       }
237 
238       /** \brief axpy operation for local function
239        *
240        *  Denoting the DoFs of the local function by \f$u_i\f$ and the basis
241        *  functions by \f$\varphi_i\f$, this function performs the following
242        *  operation:
243        *  \f[
244        *  u_i = u_i + factor \cdot \nabla\varphi_i( x )
245        *  \f]
246        *
247        *  \param[in]  x       point to evaluate jacobian of basis functions in
248        *  \param[in]  factor  axpy factor
249        */
250       template< class PointType >
axpy(const PointType & x,const JacobianRangeType & factor)251       void axpy ( const PointType &x, const JacobianRangeType &factor)
252       {
253         basisFunctionSet().axpy( x, factor, localDofVector() );
254       }
255       template< class PointType >
axpy(const PointType & x,const HessianRangeType & factor)256       void axpy ( const PointType &x, const HessianRangeType &factor)
257       {
258         basisFunctionSet().axpy( x, factor, localDofVector() );
259       }
260 
261       /** \brief axpy operation for local function
262        *
263        *  Denoting the DoFs of the local function by \f$u_i\f$ and the basis
264        *  functions by \f$\varphi_i\f$, this function performs the following
265        *  operation:
266        *  \f[
267        *  u_i = u_i + factor1 \cdot \varphi_i( x ) + factor2 \cdot \nabla\varphi_i( x )
268        *  \f]
269        *
270        *  \param[in]  x        point to evaluate basis functions in
271        *  \param[in]  factor1  axpy factor for \f$\varphi( x )\f$
272        *  \param[in]  factor2  axpy factor for \f$\nabla\varphi( x )\f$
273        */
274       template< class PointType >
axpy(const PointType & x,const RangeType & factor1,const JacobianRangeType & factor2)275       void axpy ( const PointType &x, const RangeType &factor1, const JacobianRangeType &factor2 )
276       {
277         basisFunctionSet().axpy( x, factor1, factor2, localDofVector() );
278       }
279 
280       /** \brief obtain the order of this local function
281        *
282        *  The order of a local function refers to the polynomial order required
283        *  to integrate it exactly.
284        *
285        *  \note It is not completely clear what this value should be, e.g., for
286        *        bilinear basis functions.
287        *
288        *  \returns order of the local function
289        */
order() const290       int order () const { return basisFunctionSet().order(); }
291 
292       /** \brief obtain the basis function set for this local function
293        *
294        *  \returns reference to the basis function set
295        */
basisFunctionSet() const296       const BasisFunctionSetType &basisFunctionSet () const { return basisFunctionSet_; }
297 
298       /** \brief obtain the entity, this local function lives on
299        *
300        *  \returns reference to the entity
301        */
entity() const302       const EntityType &entity () const { return basisFunctionSet().entity(); }
303 
304 
305       /** \brief evaluate the local function
306        *
307        *  \param[in]   x    evaluation point in local coordinates
308        *  \param[out]  ret  value of the function in the given point
309        */
310       template< class PointType >
evaluate(const PointType & x,RangeType & ret) const311       void evaluate ( const PointType &x, RangeType &ret ) const
312       {
313         basisFunctionSet().evaluateAll( x, localDofVector(), ret );
314       }
315 
316       /** \brief evaluate Jacobian of the local function
317        *
318        *  \note Though the Jacobian is evaluated on the reference element, the
319        *        return value is the Jacobian with respect to the actual entity.
320        *
321        *  \param[in]   x    evaluation point in local coordinates
322        *  \param[out]  ret  Jacobian of the function in the evaluation point
323        */
324       template< class PointType >
jacobian(const PointType & x,JacobianRangeType & ret) const325       void jacobian ( const PointType &x, JacobianRangeType &ret ) const
326       {
327         basisFunctionSet().jacobianAll( x, localDofVector(), ret );
328       }
329 
330       /** \brief evaluate Hessian of the local function
331        *
332        *  \note Though the Hessian is evaluated on the reference element, the
333        *        return value is the Hessian with respect to the actual entity.
334        *
335        *  \param[in]   x        evaluation point in local coordinates
336        *  \param[out]  ret  Hessian of the function in the evaluation point
337        */
338       template< class PointType >
hessian(const PointType & x,HessianRangeType & ret) const339       void hessian ( const PointType &x, HessianRangeType &ret ) const
340       {
341         basisFunctionSet().hessianAll( x, localDofVector(), ret );
342       }
343 
344       /** \brief obtain the number of local DoFs
345        *
346        *  Obtain the number of local DoFs of this local function. The value is
347        *  identical to the number of basis functons on the entity.
348        *
349        *  \returns number of local DoFs
350        */
numDofs() const351       int numDofs () const { return localDofVector().size(); }
352 
353       /** \brief obtain the number of local DoFs
354        *
355        *  Obtain the number of local DoFs of this local function. The value is
356        *  identical to the number of basis functons on the entity.
357        *
358        *  \returns number of local DoFs
359        */
size() const360       SizeType size () const { return localDofVector().size(); }
361 
362       /** \brief evaluate all basisfunctions for all quadrature points, multiply with the given factor and
363                  add the result to the local coefficients  */
364       template< class QuadratureType, class ... Vectors >
axpyQuadrature(const QuadratureType & quad,const Vectors &...values)365       void axpyQuadrature ( const QuadratureType &quad, const Vectors& ... values )
366       {
367         static_assert( sizeof...( Vectors ) > 0, "evaluateQuadrature needs to be called with at least one vector." );
368         std::ignore =
369           std::make_tuple( ( basisFunctionSet().axpy( quad, values, localDofVector() ), 1 )...);
370       }
371 
372       /** \brief evaluate all basisfunctions for all quadrature points, multiply with the given factor and
373                  add the result to the local coefficients */
374       template< class QuadratureType, class RangeVectorType, class JacobianRangeVectorType >
axpyQuadrature(const QuadratureType & quad,const RangeVectorType & rangeVector,const JacobianRangeVectorType & jacobianVector)375       void axpyQuadrature ( const QuadratureType &quad,
376                             const RangeVectorType& rangeVector,
377                             const JacobianRangeVectorType& jacobianVector )
378       {
379         basisFunctionSet().axpy( quad, rangeVector, jacobianVector, localDofVector() );
380       }
381 
382       /** \brief evaluate all basisfunctions for all quadrature points and store the results in the result vector */
383       template< class QuadratureType, class ... Vectors >
evaluateQuadrature(const QuadratureType & quad,Vectors &...vec) const384       void evaluateQuadrature( const QuadratureType &quad, Vectors& ... vec ) const
385       {
386         static_assert( sizeof...( Vectors ) > 0, "evaluateQuadrature needs to be called with at least one vector." );
387         std::ignore =
388           std::make_tuple( ( evaluateQuadrature( quad, vec, typename std::decay< decltype( vec[ 0 ] ) >::type() ), 1 )
389             ... );
390       }
391 
392       /** \brief evaluate all Jacobians for all basis functions for all quadrature points and
393        *         store the results in the result vector */
394       template< class QuadratureType, class ... Vectors >
jacobianQuadrature(const QuadratureType & quad,Vectors &...vec) const395       void jacobianQuadrature( const QuadratureType &quad, Vectors& ... vec ) const
396       {
397         static_assert( sizeof...( Vectors ) > 0, "evaluateQuadrature needs to be called with at least one vector." );
398         std::ignore =
399           std::make_tuple( ( evaluateQuadrature( quad, vec, typename std::decay< decltype( vec[ 0 ] ) >::type() ), 1 )
400             ... );
401       }
402 
403       /** \brief evaluate all hessians of all basis functions for all quadrature points and store the results in the result vector */
404       template< class QuadratureType, class ... Vectors >
hessianQuadrature(const QuadratureType & quad,Vectors &...vec) const405       void hessianQuadrature( const QuadratureType &quad, Vectors& ... vec ) const
406       {
407         // make sure vec size if large enough
408         static_assert( sizeof...( Vectors ) > 0, "evaluateQuadrature needs to be called with at least one vector." );
409         std::ignore =
410            std::make_tuple( ( evaluateQuadrature( quad, vec, typename std::decay< decltype( vec[ 0 ] ) >::type() ), 1 )
411            ... );
412       }
413 
414       /** \brief return const reference to local Dof Vector  */
localDofVector() const415       const LocalDofVectorType &localDofVector () const { return localDofVector_; }
416 
417       /** \brief return mutable reference to local Dof Vector  */
localDofVector()418       LocalDofVectorType &localDofVector () { return localDofVector_; }
419 
420 
421       /** \brief Returns true if local function if bind or init was previously called.
422        */
valid() const423       bool valid () const
424       {
425         return basisFunctionSet_.valid();
426       }
427 
428     protected:
429       /** \brief initialize the local function for an entity
430        *
431           Binds the local function to an basisFunctionSet and entity.
432 
433           \note Must be overloaded on the derived implementation class.
434 
435           \param[in] entity to bind the local function to
436        */
init(const EntityType & entity)437       void init ( const EntityType& entity )
438       {
439         DUNE_THROW(NotImplemented,"LocalFunction::init( entity ) must be overloaded on derived class!");
440       }
441 
442       /** \brief initialize the local function for an entity
443        *
444           Binds the local function to an basisFunctionSet and entity.
445 
446           \note Must be overloaded on the derived implementation class.
447 
448           \param[in] entity to bind the local function to
449        */
bind(const EntityType & entity)450       void bind ( const EntityType& entity )
451       {
452         DUNE_THROW(NotImplemented,"LocalFunction::bind( entity ) must be overloaded on derived class!");
453       }
454 
455       /** \brief clears the local function by removing the basisFunctionSet
456        *
457        */
unbind()458       void unbind ()
459       {
460         // basically sets entity pointer inside basis function set to nullptr
461         basisFunctionSet_ = BasisFunctionSetType();
462       }
463 
464       /** \brief initialize the local function for an basisFunctionSet
465        *
466           Binds the local function to an basisFunctionSet and entity.
467 
468           \note A local function must be initialized to an entity before it can
469                 be used.
470 
471           \note This function can be called multiple times to use the local
472                 function for more than one entity.
473 
474           \param[in] basisFunctionSet to bind the local function to
475        */
init(const BasisFunctionSetType & basisFunctionSet)476       void init ( const BasisFunctionSetType &basisFunctionSet )
477       {
478         basisFunctionSet_ = basisFunctionSet;
479         localDofVector_.resize( basisFunctionSet.size() );
480       }
481 
482       // evaluate local function and store results in vector of RangeTypes
483       // this method only helps to identify the correct method on
484       // the basis function set
485       template< class QuadratureType, class VectorType >
evaluateQuadrature(const QuadratureType & quad,VectorType & result,const RangeType &) const486       void evaluateQuadrature( const QuadratureType &quad, VectorType &result, const RangeType & ) const
487       {
488         basisFunctionSet().evaluateAll( quad, localDofVector(), result );
489       }
490 
491       // evaluate jacobian of local function and store result in vector of
492       // JacobianRangeTypes, this method only helps to identify the correct method on
493       // the basis function set
494       template< class QuadratureType, class VectorType >
evaluateQuadrature(const QuadratureType & quad,VectorType & result,const JacobianRangeType &) const495       void evaluateQuadrature( const QuadratureType &quad, VectorType &result, const JacobianRangeType & ) const
496       {
497         basisFunctionSet().jacobianAll( quad, localDofVector(), result );
498       }
499 
500       // evaluate jacobian of local function and store result in vector of
501       // JacobianRangeTypes, this method only helps to identify the correct method on
502       // the basis function set
503       template< class QuadratureType, class VectorType >
evaluateQuadrature(const QuadratureType & quad,VectorType & result,const HessianRangeType &) const504       void evaluateQuadrature( const QuadratureType &quad, VectorType &result, const HessianRangeType & ) const
505       {
506         basisFunctionSet().hessianAll( quad, localDofVector(), result );
507       }
508 
509       BasisFunctionSetType basisFunctionSet_;
510       LocalDofVectorType localDofVector_;
511     };
512 
513     /** \} */
514 
515   } // end namespace Fem
516 
517 } // end namespace Dune
518 
519 #endif // #ifndef DUNE_FEM_FUNCTION_LOCALFUNCTION_LOCALFUNCTION_HH
520