1 #ifndef DUNE_FEM_FUNCTION_LOCALFUNCTION_CONVERTER_HH
2 #define DUNE_FEM_FUNCTION_LOCALFUNCTION_CONVERTER_HH
3 
4 #include <functional>
5 #include <type_traits>
6 #include <utility>
7 
8 #include <dune/fem/function/common/function.hh>
9 #include <dune/fem/function/common/instationary.hh>
10 #include <dune/fem/space/common/functionspace.hh>
11 
12 
13 namespace Dune
14 {
15 
16   namespace Fem
17   {
18 
19     // LocalFunctionConverter
20     // --------------------
21 
22     /** \brief implementation of a Dune::Fem::LocalFunction on a FunctionSpace V restircted/prolongated from an other
23      *         function space W.
24      *
25      *  The HostLocalFunction is assumed to fulfill the LocalFunctioninterface.
26      *  Basically the following functions are implemented on the HostLocalFunction:
27      *  \code
28      *    template< class Point >
29      *    void evaluate ( const Point &x, RangeType &ret ) const;
30      *
31      *    template< class Point >
32      *    void jacobian ( const Point &x, JacobianRangeType &jac ) const;
33      *
34      *    tempalte< class Point >
35      *    void hessian ( const Point &x, HessianRangeType &hess ) const;
36      *
37      *    const EntityType &entity () const;
38      *
39      *    int size() const;
40      *
41      *    void init ( const EntityType & entity );
42      *  \endcode
43      *
44      *  The template paramter Converter, is used to get the restriction/prolongation onto the space V.
45      *  Converter is expected to provide the method
46      *  {Hessian,Jacobian,.}RangeType converter( Host{Hessian,Jacobian,. }RangeType );
47      *  which does the acctual mapping onto V.
48      *  The dimension of the new Range is obtained from the method Convertor::operator( HostRangeType )::dimension.
49      *
50      *  Users may prescribe how the parameter localFunction is stored by providing a
51      *  fourth template parameter, the storage policy. Further informations on the storage policy can be found in
52      *  the file dune/fem/function/common/instationary.hh.
53      *
54      *  The free-standing function
55      *  \code
56      *    Dune::Fem::localFunctionConverter
57      *  \endcode
58      *  may be used to conveniently create a new instance of a LocalFunctionConverter. Use
59      *  \code
60      *    auto g = localFunctionConverter( localFunction, Converter )
61      *  \endcode
62      *  to create an converted local function.
63      *
64      *  \tparam  HostLocalFunction original local function
65      *  \tparam  Converter structure which provides the restirction/prolongation from W to V
66      *  \tparam  StoragePolicy  storage policy
67      *
68      *  \ingroup LocalFunction
69      */
70 
71     template< class HostLocalFunction, class Converter, template< class > class Storage = __InstationaryFunction::HoldCopy >
72     class LocalFunctionConverter
73       : private Storage< HostLocalFunction >
74     {
75       typedef LocalFunctionConverter< HostLocalFunction, Converter, Storage > ThisType;
76       typedef Storage< HostLocalFunction > BaseType;
77 
78       typedef typename HostLocalFunction::RangeType HostRangeType;
79       typedef typename HostLocalFunction::JacobianRangeType HostJacobianRangeType;
80       typedef typename HostLocalFunction::HessianRangeType HostHessianRangeType;
81 
82     public:
83       // obtain new dimRange from Converter
84       static const int dimRange = decltype( std::declval< Converter >() ( std::declval< HostRangeType >() ) ) ::dimension;
85 
86       // define new FunctionSpace
87       typedef typename ToNewDimRangeFunctionSpace< typename HostLocalFunction::FunctionSpaceType, dimRange >::Type FunctionSpaceType;
88 
89       // types from HostLocalFunction
90       typedef typename HostLocalFunction::EntityType EntityType;
91 
92       // types from FunctionSpace
93       typedef typename FunctionSpaceType::DomainType DomainType;
94       typedef typename FunctionSpaceType::RangeType RangeType;
95       typedef typename FunctionSpaceType::JacobianRangeType JacobianRangeType;
96       typedef typename FunctionSpaceType::HessianRangeType HessianRangeType;
97       typedef typename FunctionSpaceType::DomainFieldType DomainFieldType;
98       typedef typename FunctionSpaceType::RangeFieldType RangeFieldType;
99 
100       static const int dimDomain = FunctionSpaceType::dimDomain;
101 
102       struct Traits
103       {
104         typedef typename FunctionSpaceType::DomainType DomainType;
105         typedef typename FunctionSpaceType::RangeType RangeType;
106         typedef typename FunctionSpaceType::JacobianRangeType JacobianRangeType;
107         typedef typename FunctionSpaceType::HessianRangeType HessianRangeType;
108         typedef typename FunctionSpaceType::DomainFieldType DomainFieldType;
109         typedef typename FunctionSpaceType::RangeFieldType RangeFieldType;
110       };
111 
LocalFunctionConverter(const HostLocalFunction & hostLocalFunction,const Converter & converter=Converter ())112       LocalFunctionConverter ( const HostLocalFunction &hostLocalFunction, const Converter &converter = Converter() )
113         : BaseType( hostLocalFunction ), converter_( converter )
114       {}
115 
LocalFunctionConverter(HostLocalFunction && hostLocalFunction,const Converter & converter=Converter ())116       LocalFunctionConverter ( HostLocalFunction &&hostLocalFunction, const Converter &converter = Converter() )
117         : BaseType( std::move( hostLocalFunction ) ), converter_( converter )
118       {}
119 
120       template< class Point >
evaluate(const Point & p,RangeType & ret) const121       void evaluate ( const Point &p, RangeType &ret ) const
122       {
123         HostRangeType hRet;
124         this->get().evaluate( p, hRet );
125         ret = converter_( hRet );
126       }
127       template< class Point >
operator ()(const Point & p) const128       RangeType operator()( const Point &p ) const
129       {
130         RangeType ret;
131         evaluate(p,ret);
132         return ret;
133       }
134 
135       template< class Point >
jacobian(const Point & p,JacobianRangeType & jac) const136       void jacobian ( const Point &p, JacobianRangeType &jac ) const
137       {
138         HostJacobianRangeType hJac;
139         this->get().jacobian( p, hJac );
140         jac = converter_( hJac );
141       }
142 
143       template< class Point >
hessian(const Point & p,HessianRangeType & hes) const144       void hessian ( const Point &p, HessianRangeType &hes ) const
145       {
146         HostHessianRangeType hHes;
147         this->get().hessian( p, hHes );
148         hes = converter_( hHes );
149       }
150 
151       template< class Quadrature, class ... Vectors >
evaluateQuadrature(const Quadrature & quad,Vectors &...vector) const152       void evaluateQuadrature ( const Quadrature &quad, Vectors& ... vector ) const
153       {
154         std::ignore = std::make_tuple(
155             ( evaluateQuadratureImp( quad, vector, vector[ 0 ] ), 1 )... );
156       }
157 
order() const158       int order () const { return this->get().order(); }
159 
entity() const160       EntityType entity () const { return this->get().entity(); }
161 
init(const EntityType & entity)162       void init ( const EntityType &entity ) { this->get().init( entity ); }
163 
164     protected:
165       template< class QuadratureType, class VectorType >
evaluateQuadratureImp(const QuadratureType & quadrature,VectorType & values,const RangeType &) const166       void evaluateQuadratureImp ( const QuadratureType &quadrature, VectorType &values, const RangeType & ) const
167       {
168         const unsigned int nop = quadrature.nop();
169         for( unsigned int qp = 0; qp < nop; ++qp )
170           evaluate( quadrature[ qp ], values[ qp ] );
171       }
172 
173       template< class QuadratureType, class VectorType >
evaluateQuadratureImp(const QuadratureType & quadrature,VectorType & values,const JacobianRangeType &) const174       void evaluateQuadratureImp ( const QuadratureType &quadrature, VectorType &values, const JacobianRangeType & ) const
175       {
176         const unsigned int nop = quadrature.nop();
177         for( unsigned int qp = 0; qp < nop; ++qp )
178           jacobian( quadrature[ qp ], values[ qp ] );
179       }
180 
181       template< class QuadratureType, class VectorType >
evaluateQuadratureImp(const QuadratureType & quadrature,VectorType & values,const HessianRangeType &) const182       void evaluateQuadratureImp ( const QuadratureType &quadrature, VectorType &values, const HessianRangeType & ) const
183       {
184         const unsigned int nop = quadrature.nop();
185         for( unsigned int qp = 0; qp < nop; ++qp )
186           hessian( quadrature[ qp ], values[ qp ] );
187       }
188 
189       Converter converter_;
190     };
191 
192 
193 
194     // localFunctionConverter
195     // ----------------------
196 
197     template< class HostLocalFunction, class Converter >
198     LocalFunctionConverter< HostLocalFunction, Converter, __InstationaryFunction::HoldCopy >
localFunctionConverter(HostLocalFunction hostLocalFunction,const Converter & converter=Converter ())199     localFunctionConverter ( HostLocalFunction hostLocalFunction, const Converter &converter = Converter() )
200     {
201       typedef LocalFunctionConverter< HostLocalFunction, Converter, __InstationaryFunction::HoldCopy > LocalFunctionConverterType;
202       return LocalFunctionConverterType( std::move( hostLocalFunction ), converter );
203     }
204 
205     template< class HostLocalFunction, class Converter >
206     LocalFunctionConverter< typename std::remove_const< HostLocalFunction >::type, Converter, __InstationaryFunction::HoldReference >
localFunctionConverter(std::reference_wrapper<HostLocalFunction> hostLocalFunction,const Converter & converter=Converter ())207     localFunctionConverter ( std::reference_wrapper< HostLocalFunction > hostLocalFunction, const Converter &converter = Converter() )
208     {
209       typedef LocalFunctionConverter< typename std::remove_const< HostLocalFunction >::type, Converter, __InstationaryFunction::HoldReference > LocalFunctionConverterType;
210       return LocalFunctionConverterType( hostLocalFunction.get(), converter );
211     }
212 
213   } // namespace Fem
214 
215 } // namespace Dune
216 
217 #endif // #ifndef DUNE_FEM_FUNCTION_LOCALFUNCTION_CONVERTER_HH
218