1 #ifndef DUNE_FEM_FUNCTION_LOCALFUNCTION_BINDABLE_HH
2 #define DUNE_FEM_FUNCTION_LOCALFUNCTION_BINDABLE_HH
3 
4 #include <dune/fem/space/common/discretefunctionspace.hh>
5 #include <dune/fem/function/common/discretefunction.hh>
6 #include <dune/fem/common/coordinate.hh>
7 #include <dune/fem/quadrature/quadrature.hh> // shouldn't be here (but otherwise the coordinate method doesn't work)
8 #include <dune/fem/common/intersectionside.hh>
9 
10 namespace Dune
11 {
12   namespace Fem
13   {
14     struct BindableFunction : public HasLocalFunction {};
15 
16     template <class GridPart, class Range>
17     struct BindableGridFunction : public BindableFunction
18     {
19       typedef GridPart GridPartType;
20       typedef typename GridPart::template Codim<0>::EntityType   EntityType;
21       typedef typename GridPart::IntersectionType                IntersectionType;
22       typedef typename EntityType::Geometry                      Geometry;
23       typedef typename Geometry::GlobalCoordinate                DomainType;
24       typedef Dune::Fem::GridFunctionSpace<GridPartType, Range>  FunctionSpaceType;
25       typedef typename FunctionSpaceType::RangeFieldType         RangeFieldType;
26       typedef typename FunctionSpaceType::RangeType              RangeType;
27       typedef typename FunctionSpaceType::JacobianRangeType      JacobianRangeType;
28       typedef typename FunctionSpaceType::HessianRangeType       HessianRangeType;
BindableGridFunctionDune::Fem::BindableGridFunction29       BindableGridFunction(const GridPart &gridPart)
30       : gridPart_(gridPart) {}
31 
bindDune::Fem::BindableGridFunction32       void bind(const EntityType &entity)
33       {
34         unbind();
35 
36         entity_.emplace( entity );
37         geometry_.emplace( this->entity().geometry() );
38       }
39 
unbindDune::Fem::BindableGridFunction40       void unbind()
41       {
42         geometry_.reset();
43         entity_.reset();
44       }
45 
bindDune::Fem::BindableGridFunction46       void bind(const IntersectionType &intersection, IntersectionSide side)
47       {
48         bind( side==IntersectionSide::in?
49               intersection.inside(): intersection.outside() );
50       }
51 
continuousDune::Fem::BindableGridFunction52       bool continuous() const { return true; }
53       template <class Point>
globalDune::Fem::BindableGridFunction54       DomainType global(const Point &x) const
55       {
56         return geometry_.value().global( Dune::Fem::coordinate(x) );
57       }
58 
59       // this method needs to be overloaded in the derived class
60       template <class Point>
61       void evaluate( const Point& x, RangeType& ret ) const;
62 
63       template <class Quadrature, class RangeArray>
evaluateDune::Fem::BindableGridFunction64       void evaluate( const Quadrature& quadrature, RangeArray& values ) const
65       {
66         const unsigned int nop = quadrature.nop();
67         values.resize( nop );
68         for( unsigned int qp=0; qp<nop; ++qp)
69         {
70           evaluate( quadrature[ qp ], values[ qp ]);
71         }
72       }
73 
gridPartDune::Fem::BindableGridFunction74       const GridPart& gridPart() const { return gridPart_; }
entityDune::Fem::BindableGridFunction75       const EntityType &entity() const { return entity_.value(); }
geometryDune::Fem::BindableGridFunction76       const Geometry& geometry() const { return geometry_.value(); }
77 
78     protected:
79       std::optional< EntityType > entity_;
80       std::optional< Geometry > geometry_;
81       const GridPart &gridPart_;
82     };
83 
84     template <class GridPart, class Range>
85     struct BindableGridFunctionWithSpace : public BindableGridFunction<GridPart,Range>
86     {
87       typedef BindableGridFunction<GridPart,Range> Base;
88       typedef GridPart GridPartType;
89       typedef typename GridPart::template Codim<0>::EntityType EntityType;
90       typedef typename EntityType::Geometry::GlobalCoordinate DomainType;
91       typedef Dune::Fem::GridFunctionSpace<GridPartType, Range> FunctionSpaceType;
92       typedef typename FunctionSpaceType::RangeFieldType RangeFieldType;
93       typedef typename FunctionSpaceType::RangeType RangeType;
94       typedef typename FunctionSpaceType::JacobianRangeType JacobianRangeType;
95       typedef typename FunctionSpaceType::HessianRangeType HessianRangeType;
96       typedef DiscreteFunctionSpaceAdapter< FunctionSpaceType, GridPartType > DiscreteFunctionSpaceType;
BindableGridFunctionWithSpaceDune::Fem::BindableGridFunctionWithSpace97       BindableGridFunctionWithSpace(const GridPart &gridPart, const std::string &name, int order)
98       : Base(gridPart),
99         space_( gridPart, order ),
100         name_(name)
101       {}
102       //! return the order of the space
orderDune::Fem::BindableGridFunctionWithSpace103       unsigned int order() const
104       {
105         return space().order();
106       }
nameDune::Fem::BindableGridFunctionWithSpace107       const std::string &name() const
108       {
109         return name_;
110       }
spaceDune::Fem::BindableGridFunctionWithSpace111       const DiscreteFunctionSpaceType &space () const
112       {
113         return space_;
114       }
115       private:
116       DiscreteFunctionSpaceType space_;
117       const std::string name_;
118     };
119 
120     namespace detail
121     {
122       template <class,class,class>
123       struct canBind
124          : std::false_type {};
125       template <class GP,class LF>
126       struct canBind<GP,LF,
127              std::void_t< decltype( std::declval<LF>().
128                             bind(std::declval<const typename GP::template Codim<0>::EntityType&>())) >>
129         : std::true_type {};
130       template <class GP,class LF>
131       using canBind_t = canBind<GP,LF,void>;
132     }
133 
134     template <class GP,class LF>
checkGridPartValid()135     constexpr detail::canBind_t<GP,LF> checkGridPartValid() { return {}; }
136 
137   } // namespace Fem
138 } // namespace Dune
139 #endif // DUNE_FEM_FUNCTION_LOCALFUNCTION_BINDABLE_HH
140