1 #ifndef DUNE_FEM_FUNCTION_LOCALFUNCTION_CONST_HH
2 #define DUNE_FEM_FUNCTION_LOCALFUNCTION_CONST_HH
3 
4 #include <algorithm>
5 #include <type_traits>
6 #include <utility>
7 
8 #include <dune/common/dynvector.hh>
9 
10 #include <dune/fem/function/localfunction/mutable.hh>
11 #include <dune/fem/function/localfunction/localfunction.hh>
12 #include <dune/fem/common/intersectionside.hh>
13 
14 namespace Dune
15 {
16 
17   namespace Fem
18   {
19 
20     // External Forward Declerations
21     // -----------------------------
22 
23     template< class >
24     struct DiscreteFunctionTraits;
25 
26     class HasLocalFunction;
27     class IsDiscreteFunction;
28     struct BindableFunction;
29 
30     // BasicConstLocalFunction
31     // -----------------------
32 
33     template < class BasisFunctionSet, class LocalDofVector >
34     class BasicConstLocalFunction
35     : public LocalFunction< BasisFunctionSet, LocalDofVector >
36     {
37       typedef BasicConstLocalFunction< BasisFunctionSet, LocalDofVector >  ThisType;
38       typedef LocalFunction< BasisFunctionSet, LocalDofVector > BaseType;
39 
40     public:
41       //! type of Dof
42       typedef typename BaseType::DofType DofType;
43 
44       //! type of Entity
45       typedef typename BaseType :: EntityType EntityType;
46 
47       //! type of BasisFunctionSet
48       typedef typename BaseType :: BasisFunctionSetType BasisFunctionSetType;
49 
50       //! type of LocalDofVector
51       typedef typename BaseType :: LocalDofVectorType LocalDofVectorType;
52 
53       //! type of SizeType
54       typedef typename BaseType::SizeType SizeType;
55 
56       //! default ctor
BasicConstLocalFunction()57       BasicConstLocalFunction () {}
58 
BasicConstLocalFunction(const BasisFunctionSetType & basisFunctionSet)59       explicit BasicConstLocalFunction ( const BasisFunctionSetType & basisFunctionSet ) : BaseType( basisFunctionSet ) {}
60 
BasicConstLocalFunction(const LocalDofVectorType & localDofVector)61       explicit BasicConstLocalFunction ( const LocalDofVectorType &localDofVector ) : BaseType( localDofVector ) {}
62 
BasicConstLocalFunction(const BasisFunctionSetType & basisFunctionSet,const LocalDofVectorType & localDofVector)63       BasicConstLocalFunction ( const BasisFunctionSetType &basisFunctionSet, const LocalDofVectorType &localDofVector )
64       : BaseType( basisFunctionSet, localDofVector )
65       {}
66 
BasicConstLocalFunction(LocalDofVectorType && localDofVector)67       explicit BasicConstLocalFunction ( LocalDofVectorType &&localDofVector ) : BaseType( localDofVector ) {}
68 
BasicConstLocalFunction(const BasisFunctionSetType & basisFunctionSet,LocalDofVectorType && localDofVector)69       BasicConstLocalFunction ( const BasisFunctionSetType &basisFunctionSet, LocalDofVectorType &&localDofVector )
70       : BaseType( basisFunctionSet, localDofVector )
71       {}
72 
BasicConstLocalFunction(const BaseType & other)73       BasicConstLocalFunction ( const BaseType &other ) : BaseType( other ) {}
74 
BasicConstLocalFunction(const ThisType & other)75       BasicConstLocalFunction ( const ThisType &other ) : BaseType( static_cast<const BaseType &>( other ) ) {}
BasicConstLocalFunction(ThisType && other)76       BasicConstLocalFunction ( ThisType && other ) : BaseType( static_cast<BaseType&&>(other) ) {}
77 
operator [](SizeType i) const78       const DofType &operator[] ( SizeType i ) const { return static_cast< const BaseType & >( *this )[ i ]; }
operator [](SizeType i)79       const DofType &operator[] ( SizeType i ) { return static_cast< const BaseType & >( *this )[ i ]; }
80 
81       using BaseType::localDofVector;
82 
83    protected:
84       using BaseType::clear;
85       using BaseType::assign;
86       using BaseType::operator +=;
87       using BaseType::operator -=;
88       using BaseType::axpy;
89     };
90 
91     /** \ingroup LocalFunction
92         \class ConstLocalDiscreteFunction
93         \brief A constant local function carrying values for one entity
94 
95         A ConstLocalDiscreteFunction is a LocalFunction which is basically doing the same as the
96         LocalFunction of a discrete function. The difference is that the local dofs
97         are not kept as references but are copied to a local storage.
98         Therefore, this is a const local function and any modification of dofs is not
99         allowed.
100 
101         \note Local DoF numbers correspond directly to array indices. Hence it
102         may be more cache efficient to generate a ConstLocalFunction when only a
103         const access to the local function is needed.
104 
105         \param DiscreteFunction type of the discrete function, the
106                                 local function shall belong to
107      */
108     template< class DiscreteFunction >
109     class ConstLocalDiscreteFunction
110     : public BasicConstLocalFunction<
111       typename DiscreteFunctionTraits< std::remove_const_t< DiscreteFunction > >::DiscreteFunctionSpaceType::BasisFunctionSetType,
112       Dune::DynamicVector< typename DiscreteFunctionTraits< std::remove_const_t< DiscreteFunction > >::DofType,
113         typename DiscreteFunctionTraits< std::remove_const_t< DiscreteFunction > >::LocalDofVectorAllocatorType
114       :: template rebind< typename DiscreteFunctionTraits< std::remove_const_t< DiscreteFunction > > ::DofType > ::other > >
115     {
116       typedef ConstLocalDiscreteFunction< DiscreteFunction > ThisType;
117       typedef BasicConstLocalFunction< typename DiscreteFunctionTraits< std::remove_const_t< DiscreteFunction > >::DiscreteFunctionSpaceType::BasisFunctionSetType,
118               Dune::DynamicVector< typename DiscreteFunctionTraits< std::remove_const_t< DiscreteFunction > >::DofType,
119               typename DiscreteFunctionTraits< std::remove_const_t< DiscreteFunction > > :: LocalDofVectorAllocatorType
120               :: template rebind< typename DiscreteFunctionTraits< std::remove_const_t< DiscreteFunction > >::DofType >::other  > >
121           BaseType;
122 
123     public:
124       typedef std::remove_const_t< DiscreteFunction > DiscreteFunctionType;
125       typedef typename DiscreteFunctionType::DiscreteFunctionSpaceType DiscreteFunctionSpaceType;
126       typedef typename DiscreteFunctionSpaceType::GridPartType GridPartType;
127       typedef typename DiscreteFunctionSpaceType::FunctionSpaceType FunctionSpaceType;
128 
129       typedef DiscreteFunctionType GridFunctionType;
130 
131       typedef typename BaseType::DofType DofType;
132       typedef typename BaseType::EntityType EntityType;
133       typedef typename GridPartType::IntersectionType IntersectionType;
134       typedef typename BaseType::BasisFunctionSetType BasisFunctionSetType;
135       typedef typename BaseType::LocalDofVectorType LocalDofVectorType;
136       typedef typename BaseType::DomainType DomainType;
137       typedef typename BaseType::RangeType RangeType;
138       typedef typename BaseType::JacobianRangeType JacobianRangeType;
139       typedef typename BaseType::HessianRangeType HessianRangeType;
140 
141       /** \brief constructor creating a local function without binding it to an
142                  entity
143 
144           Creates the local function without initializing the fields depending on
145           the current entity.
146 
147           \note Before using the local function it must be initilized by
148           \code
149           localFunction.init( entity );
150           \endcode
151 
152           \param[in] df discrete function the local function shall belong to
153        */
ConstLocalDiscreteFunction(const DiscreteFunctionType & df)154       explicit ConstLocalDiscreteFunction ( const DiscreteFunctionType &df )
155       : BaseType( LocalDofVectorType( df.localDofVectorAllocator() ) ),
156         discreteFunction_( &df )
157       {
158       }
159 
160       //! cast a MutableLocalFunction into this one !!! expensive !!!
ConstLocalDiscreteFunction(const typename DiscreteFunctionType::LocalFunctionType & localFunction)161       ConstLocalDiscreteFunction ( const typename DiscreteFunctionType::LocalFunctionType &localFunction )
162       : BaseType( localFunction.basisFunctionSet(), LocalDofVectorType( localFunction.size(), localFunction.discreteFunction().localDofVectorAllocator() ) ),
163         discreteFunction_( &localFunction.discreteFunction() )
164       {
165         std::copy( localFunction.localDofVector().begin(), localFunction.localDofVector().end(), localDofVector().begin() );
166       }
167 
168       /** \brief constructor creating a local function and binding it to an
169                  entity
170 
171           Creates the local function and initilizes the fields depending on the
172           current entity. It is not necessary, though allowed, to call init
173           before using the discrete function.
174 
175           \note The degrees of freedom are not initialized by this function.
176 
177           \param[in] df      discrete function the local function shall
178                              belong to
179           \param[in] entity  entity for initialize the local function to
180        */
ConstLocalDiscreteFunction(const DiscreteFunctionType & df,const EntityType & entity)181       ConstLocalDiscreteFunction ( const DiscreteFunctionType &df, const EntityType &entity )
182       : BaseType( df.space().basisFunctionSet( entity ), LocalDofVectorType( df.localDofVectorAllocator() )  ),
183         discreteFunction_( &df )
184       {
185         discreteFunction().getLocalDofs( entity, localDofVector() );
186       }
ConstLocalDiscreteFunction(const EntityType & entity,const DiscreteFunctionType & df)187       ConstLocalDiscreteFunction ( const EntityType &entity, const DiscreteFunctionType &df )
188       : BaseType( df.space().basisFunctionSet( entity ), LocalDofVectorType( df.localDofVectorAllocator() )  ),
189         discreteFunction_( &df )
190       {
191         discreteFunction().getLocalDofs( entity, localDofVector() );
192       }
193 
194       //! copy constructor
ConstLocalDiscreteFunction(const ThisType & other)195       ConstLocalDiscreteFunction ( const ThisType &other )
196       : BaseType( static_cast<const BaseType &>( other ) ),
197         discreteFunction_( other.discreteFunction_ )
198       {}
199 
200       //! move constructor
ConstLocalDiscreteFunction(ThisType && other)201       ConstLocalDiscreteFunction ( ThisType &&other )
202       : BaseType( static_cast< BaseType &&>( other ) ),
203         discreteFunction_( other.discreteFunction_ )
204       {}
205 
206       using BaseType::localDofVector;
207 
208       using BaseType::evaluate;
209       using BaseType::jacobian;
210       using BaseType::hessian;
211 
212       /** \brief evaluate the local function
213        *
214        *  \param[in]   x    evaluation point in local coordinates
215        *  \returns          value of the function in the given point
216        */
217       template< class Point >
evaluate(const Point & p) const218       RangeType evaluate ( const Point &p ) const
219       {
220         RangeType val;
221         evaluate( p, val );
222         return val;
223       }
224 
225       /** \brief evaluate Jacobian of the local function
226        *
227        *  \note Though the Jacobian is evaluated on the reference element, the
228        *        return value is the Jacobian with respect to the actual entity.
229        *
230        *  \param[in]   x    evaluation point in local coordinates
231        *  \returns          Jacobian of the function in the evaluation point
232        */
233       template< class Point >
jacobian(const Point & p) const234       JacobianRangeType jacobian ( const Point &p ) const
235       {
236         JacobianRangeType jac;
237         jacobian( p, jac );
238         return jac;
239       }
240 
241       /** \brief evaluate Hessian of the local function
242        *
243        *  \note Though the Hessian is evaluated on the reference element, the
244        *        return value is the Hessian with respect to the actual entity.
245        *
246        *  \param[in]   x        evaluation point in local coordinates
247        *  \returns              Hessian of the function in the evaluation point
248        */
249       template< class Point >
hessian(const Point & p) const250       HessianRangeType hessian ( const Point &p ) const
251       {
252         HessianRangeType h;
253         hessian( p, h );
254         return h;
255       }
256 
257       /** \copydoc Dune::Fem::LocalFunction :: init */
init(const EntityType & entity)258       void init ( const EntityType &entity )
259       {
260         BaseType::init( discreteFunction().space().basisFunctionSet( entity ) );
261         discreteFunction().getLocalDofs( entity, localDofVector() );
262       }
263 
bind(const EntityType & entity)264       void bind ( const EntityType &entity ) { init( entity ); }
unbind()265       void unbind () {}
bind(const IntersectionType & intersection,IntersectionSide side)266       void bind(const IntersectionType &intersection, IntersectionSide side)
267       {
268         bind( side==IntersectionSide::in?
269               intersection.inside(): intersection.outside() );
270       }
271 
discreteFunction() const272       const DiscreteFunctionType &discreteFunction() const { return *discreteFunction_; }
gridFunction() const273       const GridFunctionType &gridFunction() const { return discreteFunction(); }
274 
275     protected:
276       const DiscreteFunctionType* discreteFunction_;
277     };
278 
279 
280 
281     // ConstLocalFunction
282     // ------------------
283 
284     namespace Impl
285     {
286 
287       template< class GF, class = void >
288       struct ConstLocalFunction;
289 
290       template< class GF >
291       struct ConstLocalFunction< GF, std::enable_if_t< std::is_base_of< Fem::HasLocalFunction, GF >::value && std::is_base_of< Fem::IsDiscreteFunction, GF >::value > >
292       {
293         typedef ConstLocalDiscreteFunction< GF > Type;
294       };
295 
296       template< class GF >
297       struct ConstLocalFunction< GF, std::enable_if_t< std::is_base_of< Fem::HasLocalFunction, GF >::value && !std::is_base_of< Fem::IsDiscreteFunction, GF >::value  && std::is_class< typename GF::LocalFunctionType >::value > >
298       {
299         struct Type
300           : public GF::LocalFunctionType
301         {
302           typedef GF GridFunctionType;
303           typedef typename GridFunctionType::LocalFunctionType::EntityType EntityType;
304 
305           typedef typename GF::LocalFunctionType::DomainType DomainType;
306           typedef typename GF::LocalFunctionType::RangeType RangeType;
307           typedef typename GF::LocalFunctionType::JacobianRangeType JacobianRangeType;
308           typedef typename GF::LocalFunctionType::HessianRangeType HessianRangeType;
309 
TypeDune::Fem::Impl::ConstLocalFunction::Type310           explicit Type ( const GridFunctionType &gridFunction )
311             : GridFunctionType::LocalFunctionType( gridFunction ),
312               gridFunction_( gridFunction )
313           {}
TypeDune::Fem::Impl::ConstLocalFunction::Type314           explicit Type ( const EntityType &entity, const GridFunctionType &gridFunction )
315             : GridFunctionType::LocalFunctionType( gridFunction ),
316               gridFunction_( gridFunction )
317           { bind(entity); }
318 
319           using GF::LocalFunctionType::evaluate;
320           using GF::LocalFunctionType::jacobian;
321           using GF::LocalFunctionType::hessian;
322           using GF::LocalFunctionType::init;
323           using GF::LocalFunctionType::entity;
324 
325           //! evaluate local function
326           template< class Point >
evaluateDune::Fem::Impl::ConstLocalFunction::Type327           RangeType evaluate ( const Point &p ) const
328           {
329             RangeType val;
330             evaluate( p, val );
331             return val;
332           }
333 
334           //! jacobian of local function
335           template< class Point >
jacobianDune::Fem::Impl::ConstLocalFunction::Type336           JacobianRangeType jacobian ( const Point &p ) const
337           {
338             JacobianRangeType jac;
339             jacobian( p, jac );
340             return jac;
341           }
342 
343           //! hessian of local function
344           template< class Point >
hessianDune::Fem::Impl::ConstLocalFunction::Type345           HessianRangeType hessian ( const Point &p ) const
346           {
347             HessianRangeType h;
348             hessian( p, h );
349             return h;
350           }
351 
bindDune::Fem::Impl::ConstLocalFunction::Type352           void bind ( const EntityType &entity ) { init( entity ); }
unbindDune::Fem::Impl::ConstLocalFunction::Type353           void unbind () {}
354           template <class IntersectionType>
bindDune::Fem::Impl::ConstLocalFunction::Type355           void bind(const IntersectionType &intersection, IntersectionSide side)
356           {
357             bind( side==IntersectionSide::in?
358                   intersection.inside(): intersection.outside() );
359           }
360 
gridFunctionDune::Fem::Impl::ConstLocalFunction::Type361           const GridFunctionType &gridFunction () const { return gridFunction_; }
362 
363         private:
364           const GridFunctionType &gridFunction_;
365         };
366       };
367 
368       template< class GF >
369       struct ConstLocalFunction< GF, std::enable_if_t< std::is_base_of< Fem::BindableFunction, std::decay_t<GF> >::value && !std::is_base_of< Fem::IsDiscreteFunction, std::decay_t<GF> >::value > >
370       {
371         struct Type
372         {
373           typedef GF GridFunctionType;
374           typedef std::decay_t<GF> GridFunctionDecayType;
375           typedef typename GridFunctionDecayType::GridPartType GridPartType;
376           typedef typename GridFunctionDecayType::EntityType EntityType;
377           typedef typename GridFunctionDecayType::RangeFieldType RangeFieldType;
378           typedef typename GridFunctionDecayType::DomainType DomainType;
379           typedef typename GridFunctionDecayType::RangeType RangeType;
380           typedef typename GridFunctionDecayType::JacobianRangeType JacobianRangeType;
381           typedef typename GridFunctionDecayType::HessianRangeType HessianRangeType;
382           typedef typename GridFunctionDecayType::FunctionSpaceType FunctionSpaceType;
383 
384           template<class Arg, std::enable_if_t<std::is_constructible<GF, Arg>::value, int> = 0>
TypeDune::Fem::Impl::ConstLocalFunction::Type385           explicit Type ( Arg&& gridFunction )
386             :  gridFunction_( std::forward<Arg>(gridFunction) )
387           {}
388           template<class Arg, std::enable_if_t<std::is_constructible<GF, Arg>::value, int> = 0>
TypeDune::Fem::Impl::ConstLocalFunction::Type389           explicit Type ( const EntityType &entity, Arg&& gridFunction )
390             :  gridFunction_( std::forward<Arg>(gridFunction) )
391           { bind(entity); }
392 
393           template <class Point>
evaluateDune::Fem::Impl::ConstLocalFunction::Type394           void evaluate(const Point &x, RangeType &ret) const
395           {
396             gridFunction().evaluate(x,ret);
397           }
398           template <class Point>
jacobianDune::Fem::Impl::ConstLocalFunction::Type399           void jacobian(const Point &x, JacobianRangeType &ret) const
400           {
401             gridFunction().jacobian(x,ret);
402           }
403           template <class Point>
hessianDune::Fem::Impl::ConstLocalFunction::Type404           void hessian(const Point &x, HessianRangeType &ret) const
405           {
406             gridFunction().hessian(x,ret);
407           }
orderDune::Fem::Impl::ConstLocalFunction::Type408           unsigned int order() const { return gridFunction().order(); }
409 
410           //! evaluate local function
411           template< class Point >
evaluateDune::Fem::Impl::ConstLocalFunction::Type412           RangeType evaluate ( const Point &p ) const
413           {
414             RangeType val;
415             evaluate( p, val );
416             return val;
417           }
418 
419           //! jacobian of local function
420           template< class Point >
jacobianDune::Fem::Impl::ConstLocalFunction::Type421           JacobianRangeType jacobian ( const Point &p ) const
422           {
423             JacobianRangeType jac;
424             jacobian( p, jac );
425             return jac;
426           }
427 
428           //! hessian of local function
429           template< class Point >
hessianDune::Fem::Impl::ConstLocalFunction::Type430           HessianRangeType hessian ( const Point &p ) const
431           {
432             HessianRangeType h;
433             hessian( p, h );
434             return h;
435           }
436 
437           template< class Quadrature, class ... Vectors >
evaluateQuadratureDune::Fem::Impl::ConstLocalFunction::Type438           void evaluateQuadrature ( const Quadrature &quad, Vectors & ... values ) const
439           {
440             static_assert( sizeof...( Vectors ) > 0, "evaluateQuadrature needs to be called with at least one vector." );
441             evaluateFullQuadrature( PriorityTag<42>(), quad, values... );
442           }
443           template< class Quadrature, class Jacobians >
jacobianQuadratureDune::Fem::Impl::ConstLocalFunction::Type444           void jacobianQuadrature ( const Quadrature &quadrature, Jacobians &jacobians ) const
445           { jacobianQuadrature(quadrature,jacobians, PriorityTag<42>() ); }
446           template< class Quadrature, class Hessians >
hessianQuadratureDune::Fem::Impl::ConstLocalFunction::Type447           void hessianQuadrature ( const Quadrature &quadrature, Hessians &hessians ) const
448           { hessianQuadrature(quadrature,hessians, PriorityTag<42>() ); }
449 
bindDune::Fem::Impl::ConstLocalFunction::Type450           void bind ( const EntityType &entity ) { gridFunction_.bind( entity ); }
unbindDune::Fem::Impl::ConstLocalFunction::Type451           void unbind () { gridFunction_.unbind(); }
452           template <class IntersectionType>
bindDune::Fem::Impl::ConstLocalFunction::Type453           void bind(const IntersectionType &intersection, IntersectionSide side)
454           { defaultIntersectionBind(gridFunction_,intersection, side); }
455 
entityDune::Fem::Impl::ConstLocalFunction::Type456           const EntityType& entity() const
457           {
458             return gridFunction_.entity();
459           }
460 
gridFunctionDune::Fem::Impl::ConstLocalFunction::Type461           const GridFunctionDecayType &gridFunction () const { return gridFunction_; }
462 
463         private:
464           template< class Quadrature, class ... Vectors, class GF_=GridFunctionDecayType >
evaluateFullQuadratureDune::Fem::Impl::ConstLocalFunction::Type465           auto evaluateFullQuadrature ( PriorityTag<1>, const Quadrature &quad, Vectors & ... values ) const
466           -> std::enable_if_t< std::is_void< decltype( std::declval< const GF_& >().evaluateQuadrature(quad,values...))>::value >
467           { gridFunction().evaluateQuadrature(quad,values...); }
468           template< class Quadrature, class ... Vectors >
evaluateFullQuadratureDune::Fem::Impl::ConstLocalFunction::Type469           void evaluateFullQuadrature ( PriorityTag<0>, const Quadrature &quad, Vectors & ... values ) const
470           { std::ignore = std::make_tuple( ( evaluateSingleQuadrature( quad, values ), 1 ) ... ); }
471 
472           template< class Quadrature, class Jacobians, class GF_=GridFunctionDecayType>
jacobianQuadratureDune::Fem::Impl::ConstLocalFunction::Type473           auto jacobianQuadrature ( const Quadrature &quadrature, Jacobians &jacobians, PriorityTag<1> ) const
474           -> std::enable_if_t< std::is_void< decltype( std::declval< const GF_& >().jacobianQuadrature(quadrature,jacobians))>::value >
475           { gridFunction().jacobianQuadrature(quadrature,jacobians); }
476           template< class Quadrature, class Jacobians >
jacobianQuadratureDune::Fem::Impl::ConstLocalFunction::Type477           void jacobianQuadrature ( const Quadrature &quadrature, Jacobians &jacobians, PriorityTag<0> ) const
478           {
479             for( const auto qp : quadrature )
480               jacobians[ qp.index() ] = jacobian( qp );
481           }
482 
483           template< class Quadrature, class Hessians, class GF_=GridFunctionDecayType >
hessianQuadratureDune::Fem::Impl::ConstLocalFunction::Type484           auto hessianQuadrature ( const Quadrature &quadrature, Hessians &hessians, PriorityTag<1> ) const
485           -> std::enable_if_t< std::is_void< decltype( std::declval< const GF_& >().hessianQuadrature(quadrature,hessians))>::value >
486           { gridFunction().hessianQuadrature(quadrature,hessians); }
487           template< class Quadrature, class Hessians >
hessianQuadratureDune::Fem::Impl::ConstLocalFunction::Type488           void hessianQuadrature ( const Quadrature &quadrature, Hessians &hessians, PriorityTag<0> ) const
489           {
490             for( const auto qp : quadrature )
491               hessians[ qp.index() ] = hessian( qp );
492           }
493 
494           template< class Quadrature, class Vector >
evaluateSingleQuadratureDune::Fem::Impl::ConstLocalFunction::Type495           auto evaluateSingleQuadrature ( const Quadrature &quad, Vector &v ) const
496           -> std::enable_if_t< std::is_same< std::decay_t< decltype(v[ 0 ]) >, RangeType >::value >
497           {
498             for( const auto qp : quad )
499               v[ qp.index() ] = evaluate( qp );
500           }
501           template< class Quadrature, class Vector >
evaluateSingleQuadratureDune::Fem::Impl::ConstLocalFunction::Type502           auto evaluateSingleQuadrature ( const Quadrature &quad, Vector &v ) const
503           -> std::enable_if_t< std::is_same< std::decay_t< decltype(v[ 0 ]) >, JacobianRangeType >::value >
504           { jacobianQuadrature(quad,v); }
505           template< class Quadrature, class Vector >
evaluateSingleQuadratureDune::Fem::Impl::ConstLocalFunction::Type506           auto evaluateSingleQuadrature ( const Quadrature &quad, Vector &v ) const
507           -> std::enable_if_t< std::is_same< std::decay_t< decltype(v[ 0 ]) >, HessianRangeType >::value >
508           { hessianQuadrature(quad,v); }
509 
510           GridFunctionType gridFunction_;
511         };
512       };
513     } // namespace Impl
514 
515 
516     template< class GridFunction >
517       using ConstLocalFunction = typename Impl::ConstLocalFunction< GridFunction >::Type;
518     /**@internal Default FalseType.*/
519     template<class T, class SFINAE = void>
520       struct IsConstLocalFunction
521       : std::false_type
522       {};
523 
524     /**@internal Forward to decay_t.*/
525     template<class T>
526       struct IsConstLocalFunction<T, std::enable_if_t<!std::is_same<T, std::decay_t<T> >{}> >
527       : IsConstLocalFunction<std::decay_t<T> >
528       {};
529 
530     /**TrueType if a T can be wrapped into a Fem::ConstLocalFunction.*/
531     template<class T>
532       struct IsConstLocalFunction<
533       T,
534       std::enable_if_t<(std::is_same<T, std::decay_t<T> >{}
535           && std::is_same<T, Fem::ConstLocalFunction<typename T::GridFunctionType> >{}
536           )> >
537         : std::true_type
538         {};
539 
540 
541     /**Wrap an F into a Fem::ConstLocalFunction if directly allowed
542      * by Fem::ConstLocalFunction.
543      */
544     template<class F, std::enable_if_t<!IsConstLocalFunction<F>::value, int> = 0>
constLocalFunction(F && f)545     constexpr auto constLocalFunction(F&& f)
546     {
547       return Fem::ConstLocalFunction<std::decay_t<F> >(std::forward<F>(f));
548     }
549 
550     /**@internal Forward a Fem::ConstLocalFunction as is.*/
551     template<class F, std::enable_if_t<IsConstLocalFunction<F>::value, int> = 0>
constLocalFunction(F && f)552     constexpr decltype(auto) constLocalFunction(F&& f)
553     {
554       return std::forward<F>(f);
555     }
556 
557     template<class F, class Entity>
constLocalFunction(F && f,const Entity & entity)558     constexpr auto constLocalFunction(F&& f, const Entity &entity)
559     {
560       return Dune::Fem::ConstLocalFunction<std::decay_t<F> >(entity,std::forward<F>(f));
561     }
562 
563   } // namespace Fem
564 
565 } // namespace Dune
566 
567 #endif // #ifndef DUNE_FEM_FUNCTION_LOCALFUNCTION_CONST_HH
568