1 #ifndef DUNE_FEM_GRIDFUNCTIONADAPTER_HH
2 #define DUNE_FEM_GRIDFUNCTIONADAPTER_HH
3 
4 #include <type_traits>
5 #include <utility>
6 
7 #include <dune/common/exceptions.hh>
8 
9 //- local includes
10 #include <dune/fem/version.hh>
11 #include <dune/fem/common/coordinate.hh>
12 #include <dune/fem/function/common/discretefunction.hh>
13 
14 // for compatibility
15 #include <dune/fem/function/common/localfunctionadapter.hh>
16 
17 namespace Dune
18 {
19 
20   namespace Fem
21   {
22 
23     /** @addtogroup GridFunctionAdapter
24 
25         To plug an \ref Fem::Function "analytical function"
26         into a operator taking
27         \ref DiscreteFunctionInterface "discrete functions",
28         i.e., expecting \ref LocalFunction "local functions"
29         a wrapper can be applied to the analytical function
30         instance.
31         The resulting class is still a \ref Fem::Function "Function"
32         but with the property \ref HasLocalFunction "\" has local function \"" added.
33 
34         @{
35     */
36 
37     //- forward declaration
38     template <class FunctionImp, class GridPartImp>
39     class BasicGridFunctionAdapter;
40 
41     //! traits of GridFunctionAdapter
42     template <class FunctionImp, class GridPartImp>
43     struct BasicGridFunctionAdapterTraits
44     {
45       typedef typename std::decay_t< FunctionImp >::FunctionSpaceType FunctionSpaceType;
46 
47       typedef typename FunctionSpaceType::RangeFieldType RangeFieldType;
48       typedef typename FunctionSpaceType::DomainFieldType DomainFieldType;
49       typedef typename FunctionSpaceType::RangeType RangeType;
50       typedef typename FunctionSpaceType::DomainType DomainType;
51       typedef typename FunctionSpaceType::JacobianRangeType JacobianRangeType;
52 
53       typedef DiscreteFunctionSpaceAdapter<FunctionSpaceType,GridPartImp> DiscreteFunctionSpaceType;
54 
55       typedef GridPartImp GridPartType;
56       typedef typename GridPartType :: GridType GridType;
57       typedef typename GridPartType :: template Codim<0> :: EntityType EntityType;
58       typedef typename GridPartType :: IntersectionType IntersectionType;
59       //! type of iterator
60       typedef typename GridPartType :: template Codim<0> :: IteratorType IteratorType;
61       //! type of IndexSet
62       typedef typename GridPartType :: IndexSetType IndexSetType;
63 
64       typedef BasicGridFunctionAdapter<FunctionImp,GridPartImp> DiscreteFunctionType;
65     };
66 
67 
68 
69     // BasicGridFunctionAdapter
70     // ------------------------
71 
72     /** \brief BasicGridFunctionAdapter provides local functions for a Function.
73      */
74     template< class FunctionImp, class GridPartImp >
75     class BasicGridFunctionAdapter
76     : public Function< typename std::decay_t< FunctionImp >::FunctionSpaceType,
77                        BasicGridFunctionAdapter< FunctionImp, GridPartImp > >,
78       public HasLocalFunction
79     {
80       typedef BasicGridFunctionAdapter< FunctionImp, GridPartImp > ThisType;
81       typedef Function< typename std::decay_t< FunctionImp >::FunctionSpaceType, ThisType > BaseType;
82 
83       // Make sure the function is not a discrete functon
84       static_assert( !(std::is_convertible< FunctionImp, HasLocalFunction >::value),
85                      "FunctionType may not be a discrete function type." );
86 
87     public:
88       //! type of traits
89       typedef BasicGridFunctionAdapterTraits< FunctionImp, GridPartImp > Traits;
90 
91       //! type of function
92       typedef std::decay_t< FunctionImp > FunctionType;
93 
94       //! type of grid part
95       typedef GridPartImp GridPartType;
96 
97       //! type of discrete function space
98       typedef typename Traits::DiscreteFunctionSpaceType DiscreteFunctionSpaceType;
99 
100       // type of discrete function space
101       typedef typename Traits::FunctionSpaceType FunctionSpaceType;
102 
103       //! type of grid
104       typedef typename DiscreteFunctionSpaceType::GridType GridType;
105 
106       //! domain type (from function space)
107       typedef typename DiscreteFunctionSpaceType::DomainFieldType DomainFieldType ;
108       //! range type (from function space)
109       typedef typename DiscreteFunctionSpaceType::RangeFieldType RangeFieldType ;
110       //! domain type (from function space)
111       typedef typename DiscreteFunctionSpaceType::DomainType DomainType ;
112       //! range type (from function space)
113       typedef typename DiscreteFunctionSpaceType::RangeType RangeType ;
114       //! jacobian type (from function space)
115       typedef typename DiscreteFunctionSpaceType::JacobianRangeType JacobianRangeType;
116 
117       //! type of codim 0 entity
118       typedef typename Traits :: EntityType  EntityType;
119       typedef typename Traits :: IntersectionType IntersectionType;
120 
121     private:
122       class LocalFunction;
123 
124     public:
125       //! type of local function to export
126       typedef LocalFunction LocalFunctionType;
127 
128       // reference to function this local belongs to
BasicGridFunctionAdapter(std::string name,FunctionImp f,const GridPartType & gridPart,unsigned int order=DiscreteFunctionSpaceType::polynomialOrder)129       BasicGridFunctionAdapter ( std::string name, FunctionImp f, const GridPartType &gridPart, unsigned int order = DiscreteFunctionSpaceType::polynomialOrder )
130       : space_( gridPart, order ),
131         function_( std::move( f ) ),
132         name_( std::move( name ) )
133       {}
134 
135       // reference to function this local belongs to
BasicGridFunctionAdapter(const ThisType & other)136       BasicGridFunctionAdapter ( const ThisType &other )
137       : space_( other.space_ ),
138         function_( other.function_ ),
139         name_( other.name_ )
140       {}
141 
142       //! evaluate function on local coordinate local
evaluate(const DomainType & global,RangeType & result) const143       void evaluate ( const DomainType &global, RangeType &result ) const
144       {
145         function_.evaluate( global, result );
146       }
147 
148       //! evaluate function on local coordinate local
jacobian(const DomainType & global,JacobianRangeType & result) const149       void jacobian ( const DomainType &global, JacobianRangeType &result ) const
150       {
151         function_.jacobian(global,result);
152       }
153 
154       /** \copydoc Dune::Fem::DiscreteFunctionInterface::localFunction(const EntityType &entity) */
localFunction(const EntityType & entity)155       LocalFunctionType localFunction ( const EntityType &entity )
156       {
157         return LocalFunctionType( entity, *this );
158       }
159 
160       /** \copydoc Dune::Fem::DiscreteFunctionInterface::localFunction(const EntityType &entity) const */
localFunction(const EntityType & entity) const161       const LocalFunctionType localFunction ( const EntityType &entity ) const
162       {
163         return LocalFunctionType( entity, *this );
164       }
165 
166       /** \copydoc Dune::Fem::DiscreteFunctionInterface::name() const */
name() const167       const std::string &name () const
168       {
169         return name_;
170       }
171 
172       /** \copydoc Dune::Fem::DiscreteFunctionInterface::space() const */
space() const173       const DiscreteFunctionSpaceType &space () const
174       {
175         return space_;
176       }
177 
gridPart() const178       const GridPartType &gridPart () const
179       {
180         return space().gridPart();
181       }
182 
183       //! return true, probably
order() const184       inline int order () const
185       {
186         return space().order();
187       }
188 
189       //! return true, probably
continuous() const190       inline bool continuous () const
191       {
192         return space().continuous();
193       }
194 
195     protected:
196       DiscreteFunctionSpaceType space_;
197       FunctionImp function_;
198       const std::string name_;
199     };
200 
201 
202 
203     // BasicGridFunctionAdapter::LocalFunction
204     // ---------------------------------------
205 
206     template< class Function, class GridPart >
207     class BasicGridFunctionAdapter< Function, GridPart >::LocalFunction
208     {
209       typedef LocalFunction ThisType;
210       typedef BasicGridFunctionAdapter< Function, GridPart > DiscreteFunctionType;
211 
212     public:
213       //! function space type
214       typedef typename Traits::FunctionSpaceType FunctionSpaceType;
215 
216       //! domain field type (from function space)
217       typedef typename FunctionSpaceType::DomainFieldType DomainFieldType;
218       //! range field type (from function space)
219       typedef typename FunctionSpaceType::RangeFieldType RangeFieldType;
220       //! domain dimension (from function space)
221       static const int dimDomain = GridPart::GridType::dimensionworld;
222       //! range dimension (from function space)
223       static const int dimRange = FunctionSpaceType::dimRange;
224 
225       //! domain type (from function space)
226       typedef typename FunctionSpaceType::DomainType DomainType;
227       //! range type (from function space)
228       typedef typename FunctionSpaceType::RangeType RangeType;
229       //! jacobian type (from function space)
230       typedef typename FunctionSpaceType::JacobianRangeType JacobianRangeType;
231       //! hessian type (from function space)
232       typedef typename FunctionSpaceType::HessianRangeType HessianRangeType;
233 
234       //! entity type
235       typedef typename Traits::EntityType EntityType;
236       typedef typename Traits::IntersectionType IntersectionType;
237       //! local coordinate type
238       typedef typename EntityType::Geometry::LocalCoordinate LocalCoordinateType;
239       //! local dimension
240       static const int dimLocal = LocalCoordinateType::dimension;
241 
242       //! constructor initializing local function
LocalFunction(const EntityType & entity,const DiscreteFunctionType & df)243       LocalFunction ( const EntityType &entity, const DiscreteFunctionType &df )
244       : function_( &df.function_ ),
245         entity_( &entity ),
246         order_( df.space().order() )
247       {}
248 
LocalFunction(const DiscreteFunctionType & df)249       LocalFunction ( const DiscreteFunctionType &df )
250       : function_( &df.function_ ),
251         entity_( 0 ),
252         order_( df.space().order() )
253       {}
254 
255       //! copy constructor
256       LocalFunction ( const LocalFunction &other ) = default;
257 
258       //! evaluate local function
259       template< class PointType >
evaluate(const PointType & x,RangeType & ret) const260       void evaluate ( const PointType &x, RangeType &ret ) const
261       {
262         const auto geometry = entity().geometry();
263         auto global = geometry.global( coordinate( x ) );
264         function().evaluate( global, ret );
265       }
266       template< class PointType >
operator ()(const PointType & x) const267       RangeType operator() ( const PointType &x ) const
268       {
269         RangeType ret;
270         evaluate(x,ret);
271         return ret;
272       }
273 
274       //! jacobian of local function
275       template< class PointType >
jacobian(const PointType & x,JacobianRangeType & ret) const276       void jacobian ( const PointType &x, JacobianRangeType &ret ) const
277       {
278         const auto geometry = entity().geometry();
279         auto global = geometry.global( coordinate( x ) );
280         function().jacobian( global, ret );
281 
282         if( dimLocal != dimDomain )
283         {
284           // This computes the projection to the tangential space
285           // (i.e. the hyperplane this entity is contained in). This
286           // is done in a generic way by first projecting to the local
287           // tangential space of the reference elment, and then
288           // projecting back to the ambient space.
289 
290           const auto gjt = geometry.jacobianTransposed( coordinate( x ) );
291           const auto gjit = geometry.jacobianInverseTransposed( coordinate( x ) );
292 
293           FieldVector< RangeFieldType, dimLocal > tmp;
294           for( auto i = 0; i < dimRange; ++i )
295           {
296             gjit.mtv( ret[ i ], tmp );
297             gjt.mtv( tmp, ret[ i ] );
298           }
299         }
300       }
301 
302       //! hessian of local function
303       template< class PointType >
hessian(const PointType & x,HessianRangeType & ret) const304       void hessian ( const PointType &x, HessianRangeType &ret ) const
305       {
306         DUNE_THROW( NotImplemented, "Method hessian() not implemented yet" );
307       }
308 
309       //! evaluate function or jacobian of function for given quadrature
310       template < class QuadratureType, class ... Vectors >
evaluateQuadrature(const QuadratureType & quadrature,Vectors &...values) const311       void evaluateQuadrature( const QuadratureType& quadrature, Vectors& ... values ) const
312       {
313         static_assert( sizeof...( Vectors ) > 0, "evaluateQuadrature needs to be called with at least one vector." );
314         std::ignore = std::make_tuple( ( evaluateQuadratureImp( quadrature, values ), 1 ) ... );
315       }
316 
order() const317       int order () const { return order_; }
318 
319       //! init local function
init(const EntityType & entity)320       void init ( const EntityType &entity )
321       {
322         entity_ = &entity;
323       }
324 
entity() const325       const EntityType &entity () const
326       {
327         assert( entity_ );
328         return *entity_;
329       }
330 
331     protected:
332       template < class QuadratureType, class VectorType >
evaluateQuadratureImp(const QuadratureType & quadrature,VectorType & values) const333       auto evaluateQuadratureImp( const QuadratureType& quadrature, VectorType& values ) const
334       -> std::enable_if_t< std::is_same< std::decay_t< decltype(values[ 0 ] ) >, RangeType >::value >
335       {
336         for( auto qp : quadrature )
337           evaluate( qp, values[ qp.index() ] );
338       }
339 
340       template < class QuadratureType, class VectorType >
evaluateQuadratureImp(const QuadratureType & quadrature,VectorType & values) const341       auto evaluateQuadratureImp( const QuadratureType& quadrature, VectorType& values ) const
342       -> std::enable_if_t< std::is_same< std::decay_t< decltype(values[ 0 ] ) >, JacobianRangeType >::value >
343       {
344         for( auto qp : quadrature )
345           jacobian( qp, values[ qp.index() ] );
346       }
347 
function() const348       const FunctionType &function () const
349       {
350         return *function_;
351       }
352 
353       const FunctionType *function_;
354       const EntityType *entity_;
355       int order_;
356     };
357 
358 
359 
360     // GridFunctionAdapter
361     // -------------------
362 
363     template< class Function, class GridPart >
364     using GridFunctionAdapter = BasicGridFunctionAdapter< const Function &, GridPart >;
365 
366 
367 
368     // gridFunctionAdapter
369     // -------------------
370 
371     /**
372      * \brief convert a function to a grid function
373      *
374      * \param[in]  name      name of the grid function
375      * \param[in]  function  function to convert
376      * \param[in]  gridPart  grid part to restrict the domain to
377      * \param[in]  order     polynomial order to report
378      *
379      * \note This version accepts only lvalue references. The grid function only
380      *       references the original function.
381      **/
382     template< class Function, class GridPart >
383     inline static GridFunctionAdapter< Function, GridPart >
gridFunctionAdapter(std::string name,const Function & function,const GridPart & gridPart,unsigned int order)384     gridFunctionAdapter ( std::string name, const Function &function, const GridPart &gridPart, unsigned int order )
385     {
386       return GridFunctionAdapter< Function, GridPart >( std::move( name ), function, gridPart, order );
387     }
388 
389     /**
390      * \brief convert a function to a grid function
391      *
392      * \param[in]  function  function to convert
393      * \param[in]  gridPart  grid part to restrict the domain to
394      * \param[in]  order     polynomial order to report
395      *
396      * \note This version accepts only lvalue references. The grid function only
397      *       references the original function.
398      **/
399     template< class Function, class GridPart >
400     inline static GridFunctionAdapter< Function, GridPart >
gridFunctionAdapter(const Function & function,const GridPart & gridPart,unsigned int order)401     gridFunctionAdapter ( const Function &function, const GridPart &gridPart, unsigned int order )
402     {
403       return GridFunctionAdapter< Function, GridPart >( std::string(), function, gridPart, order );
404     }
405 
406     /**
407      * \brief convert a function to a grid function
408      *
409      * \param[in]  name      name of the grid function
410      * \param[in]  function  function to convert
411      * \param[in]  gridPart  grid part to restrict the domain to
412      * \param[in]  order     polynomial order to report
413      *
414      * \note This version accepts only lvalue references. The grid function only
415      *       references the original function.
416      **/
417     template< class Function, class GridPart >
418     inline static GridFunctionAdapter< Function, GridPart >
gridFunctionAdapter(std::string name,Function & function,const GridPart & gridPart,unsigned int order)419     gridFunctionAdapter ( std::string name, Function &function, const GridPart &gridPart, unsigned int order )
420     {
421       const Function& cf = function;
422       return gridFunctionAdapter( name, cf, gridPart, order );
423     }
424 
425     /**
426      * \brief convert a function to a grid function
427      *
428      * \param[in]  function  function to convert
429      * \param[in]  gridPart  grid part to restrict the domain to
430      * \param[in]  order     polynomial order to report
431      *
432      * \note This version accepts only lvalue references. The grid function only
433      *       references the original function.
434      **/
435     template< class Function, class GridPart >
436     inline static GridFunctionAdapter< Function, GridPart >
gridFunctionAdapter(Function & function,const GridPart & gridPart,unsigned int order)437     gridFunctionAdapter ( Function &function, const GridPart &gridPart, unsigned int order )
438     {
439       const Function& cf = function;
440       return gridFunctionAdapter( cf, gridPart, order );
441     }
442 
443     /**
444      * \brief convert a function to a grid function
445      *
446      * \param[in]  name      name of the grid function
447      * \param[in]  function  function to convert
448      * \param[in]  gridPart  grid part to restrict the domain to
449      * \param[in]  order     polynomial order to report
450      *
451      * \note This version accepts only rvalue references. The original function
452      *       is move-constructed into the grid function.
453      **/
454     template< class Function, class GridPart >
455     inline static BasicGridFunctionAdapter< Function, GridPart >
gridFunctionAdapter(std::string name,Function && function,const GridPart & gridPart,unsigned int order)456     gridFunctionAdapter ( std::string name, Function &&function, const GridPart &gridPart, unsigned int order )
457     {
458       return BasicGridFunctionAdapter< Function, GridPart >( std::move( name ), std::move( function ), gridPart, order );
459     }
460 
461     /**
462      * \brief convert a function to a grid function
463      *
464      * \param[in]  function  function to convert
465      * \param[in]  gridPart  grid part to restrict the domain to
466      * \param[in]  order     polynomial order to report
467      *
468      * \note This version accepts only rvalue references. The original function
469      *       is move-constructed into the grid function.
470      **/
471     template< class Function, class GridPart >
472     inline static BasicGridFunctionAdapter< Function, GridPart >
gridFunctionAdapter(Function && function,const GridPart & gridPart,unsigned int order)473     gridFunctionAdapter ( Function &&function, const GridPart &gridPart, unsigned int order )
474     {
475       return BasicGridFunctionAdapter< Function, GridPart >( std::string(), std::move( function ), gridPart, order );
476     }
477 
478 
479 
480     namespace
481     {
482       template <class FunctionImp,class GridPartType,bool>
483       struct ConvertDFTypeHelper;
484 
485       template <class FunctionImp,class GridPartType>
486       struct ConvertDFTypeHelper<FunctionImp,GridPartType,true>
487       {
488         typedef ConvertDFTypeHelper<FunctionImp,GridPartType,true> ThisType;
489         enum {compatible = std::is_convertible<GridPartType,typename FunctionImp::DiscreteFunctionSpaceType::GridPartType>::value};
490         typedef FunctionImp FunctionType;
491         typedef typename FunctionType::DiscreteFunctionSpaceType DFSType;
ConvertDFTypeHelperDune::Fem::__anon1d2799320111::ConvertDFTypeHelper492         ConvertDFTypeHelper(const std::string& name,const FunctionImp& func,const GridPartType& gp) :
493           func_(func)
494         {}
ConvertDFTypeHelperDune::Fem::__anon1d2799320111::ConvertDFTypeHelper495         ConvertDFTypeHelper(const ConvertDFTypeHelper& other) :
496           func_(other.func_)
497         {}
functionDune::Fem::__anon1d2799320111::ConvertDFTypeHelper498         const FunctionType& function() const
499         {
500           return func_;
501         }
spaceDune::Fem::__anon1d2799320111::ConvertDFTypeHelper502         const DFSType& space() const
503         {
504           return func_.space();
505         }
506         private:
507         const FunctionImp& func_;
508       };
509 
510       template <class FunctionImp,class GridPartType>
511       struct ConvertDFTypeHelper<FunctionImp,GridPartType,false>
512         : GridFunctionAdapter<FunctionImp,GridPartType>
513       {
514         typedef ConvertDFTypeHelper<FunctionImp,GridPartType,false> ThisType;
515         typedef GridFunctionAdapter<FunctionImp,GridPartType> BaseType;
516         typedef BaseType FunctionType;
517         typedef typename FunctionType::DiscreteFunctionSpaceType DFSType;
ConvertDFTypeHelperDune::Fem::__anon1d2799320111::ConvertDFTypeHelper518         ConvertDFTypeHelper(const std::string& name,const FunctionImp& func,const GridPartType& gp) :
519           BaseType(name,func,gp)
520         {}
ConvertDFTypeHelperDune::Fem::__anon1d2799320111::ConvertDFTypeHelper521         ConvertDFTypeHelper(const ConvertDFTypeHelper& other) :
522           BaseType(other)
523         {}
functionDune::Fem::__anon1d2799320111::ConvertDFTypeHelper524         const FunctionType& function() const
525         {
526           return *this;
527         }
spaceDune::Fem::__anon1d2799320111::ConvertDFTypeHelper528         const DFSType& space() const
529         {
530           return BaseType::space();
531         }
532       };
533     }
534 
535     template< class FunctionImp, class GridPartImp >
536     class ConvertToGridFunction
537     : public Function< typename FunctionImp::FunctionSpaceType,
538                        ConvertToGridFunction< FunctionImp, GridPartImp > >,
539       public HasLocalFunction
540     {
541       typedef ConvertToGridFunction< FunctionImp, GridPartImp > ThisType;
542       typedef Function< typename FunctionImp::FunctionSpaceType, ThisType > BaseType;
543       static const bool hasLocalFunction = std::is_convertible< FunctionImp, HasLocalFunction >::value;
544       typedef ConvertDFTypeHelper< FunctionImp, GridPartImp, hasLocalFunction > Helper;
545       typedef typename Helper::FunctionType ConvertedType;
546 
547     public:
548       typedef FunctionImp FunctionType;
549       typedef GridPartImp GridPartType;
550 
551       //! type of discrete function space
552       typedef typename ConvertedType::DiscreteFunctionSpaceType DiscreteFunctionSpaceType;
553       // type of discrete function space
554       typedef typename ConvertedType::FunctionSpaceType FunctionSpaceType;
555 
556       //! type of grid
557       typedef typename DiscreteFunctionSpaceType::GridType GridType;
558 
559       //! domain type (from function space)
560       typedef typename DiscreteFunctionSpaceType::DomainFieldType DomainFieldType ;
561       //! range type (from function space)
562       typedef typename DiscreteFunctionSpaceType::RangeFieldType RangeFieldType ;
563       //! domain type (from function space)
564       typedef typename DiscreteFunctionSpaceType::DomainType DomainType ;
565       //! range type (from function space)
566       typedef typename DiscreteFunctionSpaceType::RangeType RangeType ;
567       //! jacobian type (from function space)
568       typedef typename DiscreteFunctionSpaceType::JacobianRangeType JacobianRangeType;
569 
570       //! type of codim 0 entity
571       typedef typename GridPartType :: template Codim<0> :: EntityType  EntityType;
572 
573       //! type of local function to export
574       typedef typename ConvertedType::LocalFunctionType LocalFunctionType;
575 
576       //! constructor
ConvertToGridFunction(const std::string & name,const FunctionImp & function,const GridPartType & gridPart)577       ConvertToGridFunction ( const std::string &name,
578                               const FunctionImp &function,
579                               const GridPartType &gridPart )
580       : name_( name ),
581         helper_( name, function, gridPart )
582       {}
583 
ConvertToGridFunction(const ThisType & other)584       ConvertToGridFunction ( const ThisType &other )
585       : name_( other.name_ ),
586         helper_( other.helper_ )
587       {}
588 
589       //! evaluate function on local coordinate local
evaluate(const DomainType & global,RangeType & result) const590       void evaluate ( const DomainType &global, RangeType &result ) const
591       {
592         helper_.function().evaluate(global,result);
593       }
594 
595       /** \copydoc Dune::Fem::DiscreteFunctionInterface::localFunction(const EntityType &entity) const */
localFunction(const EntityType & entity) const596       const LocalFunctionType localFunction( const EntityType &entity ) const
597       {
598         return helper_.function().localFunction(entity);
599       }
600 
601       /** \copydoc Dune::Fem::DiscreteFunctionInterface::localFunction(const EntityType &entity) */
localFunction(const EntityType & entity)602       LocalFunctionType localFunction( const EntityType &entity )
603       {
604         return helper_.function().localFunction(entity);
605       }
606 
607       /** \copydoc Dune::Fem::DiscreteFunctionInterface::name */
name() const608       const std::string &name() const
609       {
610         return name_;
611       }
612 
space() const613       const DiscreteFunctionSpaceType &space() const
614       {
615         return helper_.space();
616       }
617 
618     private:
619       const std::string name_;
620       Helper helper_;
621     };
622 
623     template< class Function, class GridPart >
624     inline ConvertToGridFunction< Function, GridPart >
convertToGridFunction(const std::string & name,const Function & function,const GridPart & gridPart)625     convertToGridFunction ( const std::string &name,
626                             const Function &function,
627                             const GridPart &gridPart )
628     {
629       return ConvertToGridFunction< Function, GridPart >( name, function, gridPart );
630     }
631 
632   } // namespace Fem
633 
634 } // namespace Dune
635 
636 //@}
637 
638 #endif // #ifndef DUNE_DISCRETEFUNCTIONADAPTER_HH
639