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