DUNE-FEM (unstable)

orthonormal.hh
1#ifndef DUNE_FEM_SPACE_SHAPEFUNCTIONSET_ORTHONORMAL_HH
2#define DUNE_FEM_SPACE_SHAPEFUNCTIONSET_ORTHONORMAL_HH
3
4#include <cassert>
5#include <cstddef>
6#include <memory>
7
9
10#include <dune/fem/common/coordinate.hh>
11#include <dune/fem/quadrature/quadrature.hh>
12
13#include <dune/fem/space/common/functionspace.hh>
14#include <dune/fem/space/shapefunctionset/orthonormal/orthonormalbase_1d.hh>
15#include <dune/fem/space/shapefunctionset/orthonormal/orthonormalbase_2d.hh>
16#include <dune/fem/space/shapefunctionset/orthonormal/orthonormalbase_3d.hh>
17
18#if HAVE_DUNE_LOCALFUNCTIONS
19#include <dune/localfunctions/orthonormal.hh>
20#endif
21
22namespace Dune
23{
24
25 namespace Fem
26 {
27
28#ifndef DOXYGEN
29
30 // OrthonormalShapeFunctions
31 // -------------------------
32
33 template< int dimension >
34 struct OrthonormalShapeFunctions;
35
36 template<>
37 struct OrthonormalShapeFunctions< 1 >
38 {
39 static constexpr std::size_t size ( int order )
40 {
41 return static_cast< std::size_t >( order+1 );
42 }
43 };
44
45 template<>
46 struct OrthonormalShapeFunctions< 2 >
47 {
48 static constexpr std::size_t size ( int order )
49 {
50 return static_cast< std::size_t >( (order+2)*(order+1)/2 );
51 }
52 };
53
54 template<>
55 struct OrthonormalShapeFunctions< 3 >
56 {
57 static constexpr std::size_t size ( int order )
58 {
59 return static_cast< std::size_t >( ((order+1)*(order+2)*(2*order+3)/6+(order+1)*(order+2)/2)/2 );
60 }
61 };
62
63#endif // #ifndef DOXYGEN
64
65
66
67 // OrthonormalShapeFunctionSet
68 // ---------------------------
69
70 template< class FunctionSpace >
71 class OrthonormalShapeFunctionSet
72 {
73 typedef OrthonormalShapeFunctionSet< FunctionSpace > ThisType;
74
75 static_assert( FunctionSpace::dimDomain <= 3, "OrthonormalShapeFunctionSet only implemented up to domain dimension 3" );
76 static_assert( FunctionSpace::dimRange == 1, "OrthonormalShapeFunctionSet only implemented for scalar function spaces" );
77
78 public:
80 typedef FunctionSpace FunctionSpaceType;
81
82 private:
83 typedef typename FunctionSpaceType::DomainFieldType DomainFieldType;
84 typedef typename FunctionSpaceType::RangeFieldType RangeFieldType;
85
86 typedef RangeFieldType (*Evaluate) ( const int, const DomainFieldType * );
87 typedef void (*Jacobian) ( const int i, const DomainFieldType *, RangeFieldType * );
88
89 // hessian is only available for 2d-simplices (aka triangles)
90 typedef RangeFieldType Array[ 3 ];
91 typedef void (*Hessian) ( const int i, const DomainFieldType *, Array & );
92
93 typedef OrthonormalBase_1D< DomainFieldType, RangeFieldType > OrthonormalBase1d;
94 typedef OrthonormalBase_2D< DomainFieldType, RangeFieldType > OrthonormalBase2d;
95 typedef OrthonormalBase_3D< DomainFieldType, RangeFieldType > OrthonormalBase3d;
96
97 static void setFunctionPointers(const Dune::GeometryType& geomType,
98 Evaluate &evaluate, Jacobian &jacobian )
99 {
100 if( geomType.isLine() )
101 {
102 evaluate = OrthonormalBase1d::eval_line;
103 jacobian = OrthonormalBase1d::grad_line;
104 return ;
105 }
106 else if( geomType.isQuadrilateral() )
107 {
108 evaluate = OrthonormalBase2d::eval_quadrilateral_2d;
109 jacobian = OrthonormalBase2d::grad_quadrilateral_2d;
110 return ;
111 }
112 else if( geomType.isTriangle() )
113 {
114 evaluate = OrthonormalBase2d::eval_triangle_2d;
115 jacobian = OrthonormalBase2d::grad_triangle_2d;
116 return ;
117 }
118 else if( geomType.isHexahedron() )
119 {
120 evaluate = OrthonormalBase3d::eval_hexahedron_3d;
121 jacobian = OrthonormalBase3d::grad_hexahedron_3d;
122 return ;
123 }
124 else if ( geomType.isTetrahedron() )
125 {
126 evaluate = OrthonormalBase3d::eval_tetrahedron_3d;
127 jacobian = OrthonormalBase3d::grad_tetrahedron_3d;
128 return ;
129 }
130 else if( geomType.isPrism() )
131 {
132 evaluate = OrthonormalBase3d::eval_prism_3d;
133 jacobian = OrthonormalBase3d::grad_prism_3d;
134 return ;
135 }
136 else if ( geomType.isPyramid() )
137 {
138 evaluate = OrthonormalBase3d::eval_pyramid_3d;
139 jacobian = OrthonormalBase3d::grad_pyramid_3d;
140 return ;
141 }
142
143 DUNE_THROW(InvalidStateException,"Invalid geometry type " << geomType );
144 }
145
146 public:
148 static const int dimension = FunctionSpaceType::dimDomain;
149
151 typedef typename FunctionSpaceType::DomainType DomainType;
153 typedef typename FunctionSpaceType::RangeType RangeType;
155 typedef typename FunctionSpaceType::JacobianRangeType JacobianRangeType;
157 typedef typename FunctionSpaceType::HessianRangeType HessianRangeType;
158
159#if HAVE_DUNE_LOCALFUNCTIONS
160 typedef OrthonormalLocalFiniteElement< dimension, DomainType, RangeType> OrthonormalLocalFiniteElementType;
161 static const bool haveLocalFunctions_ = true;
162#else
163 typedef int OrthonormalLocalFiniteElementType;
164 static const bool haveLocalFunctions_ = false;
165#endif
170 OrthonormalShapeFunctionSet () = default;
171
172 OrthonormalShapeFunctionSet ( GeometryType type, int order )
173 : order_( order ),
174 evaluate_( nullptr ),
175 jacobian_( nullptr ),
176 hessian_( nullptr ),
177 onbElem_()
178 {
179 // for type none simply create cube basis function set.
180 if( type.isNone() )
181 type = Dune::GeometryTypes::cube(type.dim());
182
183 // set functions pointers for evaluate and jacobian
184 // depending on geometry type
185 setFunctionPointers( type, evaluate_, jacobian_ );
186 assert( evaluate_ );
187 assert( jacobian_ );
188
189 if constexpr ( dimension == 2 )
190 {
191 if( type.isTriangle() )
192 hessian_ = OrthonormalBase2d::hess_triangle_2d;
193 else if( type.isQuadrilateral() )
194 hessian_ = OrthonormalBase2d::hess_quadrilateral_2d;
195 }
196 else if constexpr ( dimension == 3 && haveLocalFunctions_ )
197 onbElem_.reset( new OrthonormalLocalFiniteElementType( type, order ) );
198
199 }
200
201 OrthonormalShapeFunctionSet ( const ThisType & ) = default;
202
203 OrthonormalShapeFunctionSet ( ThisType && ) = default;
204
211 OrthonormalShapeFunctionSet &operator= ( const ThisType & ) = default;
212
213 OrthonormalShapeFunctionSet &operator= ( ThisType && ) = default;
214
222 int order () const { return order_; }
223
225 std::size_t constexpr size () const { return size( order() ); }
226
228 static std::size_t constexpr size ( int order )
229 {
230 return OrthonormalShapeFunctions< dimension >::size( order );
231 }
232
234 template< class Point, class Functor >
235 void evaluateEach ( const Point &x, Functor functor ) const
236 {
237 const DomainType y = Dune::Fem::coordinate( x );
238 RangeType value;
239 const std::size_t size = this->size();
240 for( std::size_t i = 0; i < size; ++i )
241 {
242 evaluate( i, y, value );
243 functor( i, value );
244 }
245 }
246
248 template< class Point, class Functor >
249 void jacobianEach ( const Point &x, Functor functor ) const
250 {
251 const DomainType y = Dune::Fem::coordinate( x );
252 JacobianRangeType jacobian;
253 const std::size_t size = this->size();
254 for( std::size_t i = 0; i < size; ++i )
255 {
256 this->jacobian( i, y, jacobian );
257 functor( i, jacobian );
258 }
259 }
260
262 template< class Point, class Functor >
263 void hessianEach ( const Point &x, Functor functor ) const
264 {
265 const DomainType y = Dune::Fem::coordinate( x );
266 if constexpr ( dimension == 2 )
267 {
268 HessianRangeType hessian;
269 const std::size_t size = this->size();
270 for( std::size_t i = 0; i < size; ++i )
271 {
272 this->hessian( i, y, hessian );
273 functor( i, hessian );
274 }
275 }
276 else if constexpr( dimension == 3 && haveLocalFunctions_ )
277 {
278 const std::size_t size = this->size();
279 // for p < 2 this is simply zero
280 if ( order_ < 2 )
281 {
282 HessianRangeType hessian(0);
283 for( std::size_t i = 0; i < size; ++i )
284 {
285 // convert to our own data type to avoid
286 // conversion conflicts in functor call
287 functor( i, hessian );
288 }
289 return ;
290 }
291
292 typedef typename OrthonormalLocalFiniteElementType::Traits::LocalBasisType::HessianType HessianType;
293 std::vector< HessianType > hessians;
294 onbElem_->localBasis().evaluateHessian( y, hessians );
295 HessianRangeType hessian;
296 for( std::size_t i = 0; i < size; ++i )
297 {
298 // convert to our own data type to avoid
299 // conversion conflicts in functor call
300 hessian = hessians[ i ];
301 functor( i, hessian );
302 }
303 }
304 else
305 {
306 std::abort();
307 }
308 }
309
312 private:
313 void evaluate ( std::size_t i, const DomainType &x, RangeType &value ) const
314 {
315 value[ 0 ] = evaluate_( i, &x[ 0 ] );
316 }
317
318 void jacobian ( std::size_t i, const DomainType &x, JacobianRangeType &jacobian ) const
319 {
320 jacobian_( i, &x[ 0 ], &jacobian[ 0 ][ 0 ] );
321 }
322
323 void hessian ( std::size_t i, const DomainType &x, HessianRangeType &hessian ) const
324 {
325 assert( hessian_ );
326 if constexpr (dimension == 2 )
327 {
328 RangeFieldType values[] = { 0, 0, 0 };
329 hessian_( i , &x[ 0 ], values );
330 for( unsigned int j = 0; j < FunctionSpaceType::dimDomain; ++j )
331 for( unsigned int k = 0; k < FunctionSpaceType::dimDomain; ++k )
332 hessian[ 0 ][ j ][ k ] = values[ j + k ];
333 }
334 else
335 {
336 std::abort();
337 }
338 }
339
340 int order_;
341 Evaluate evaluate_;
342 Jacobian jacobian_;
343 Hessian hessian_;
344
345 mutable std::shared_ptr< OrthonormalLocalFiniteElementType > onbElem_;
346 };
347
348
349 } // namespace Fem
350
351} // namespace Dune
352
353#endif // #ifndef DUNE_FEM_SPACE_SHAPEFUNCTIONSET_ORTHONORMAL_HH
Definition: explicitfieldvector.hh:75
FunctionSpaceTraits::DomainFieldType DomainFieldType
Intrinsic type used for values in the domain field (usually a double)
Definition: functionspaceinterface.hh:60
FunctionSpaceTraits::RangeType RangeType
Type of range vector (using type of range field) has a Dune::FieldVector type interface.
Definition: functionspaceinterface.hh:71
@ dimDomain
dimension of domain vector space
Definition: functionspaceinterface.hh:46
@ dimRange
dimension of range vector space
Definition: functionspaceinterface.hh:48
FunctionSpaceTraits::LinearMappingType JacobianRangeType
Intrinsic type used for the jacobian values has a Dune::FieldMatrix type interface.
Definition: functionspaceinterface.hh:75
FunctionSpaceTraits::DomainType DomainType
Type of domain vector (using type of domain field) has a Dune::FieldVector type interface.
Definition: functionspaceinterface.hh:67
FunctionSpaceTraits::RangeFieldType RangeFieldType
Intrinsic type used for values in the range field (usually a double)
Definition: functionspaceinterface.hh:63
A vector valued function space.
Definition: functionspace.hh:60
Unique label for each type of entities that can occur in DUNE grids.
Definition: type.hh:114
constexpr bool isPyramid() const
Return true if entity is a pyramid.
Definition: type.hh:304
constexpr bool isTetrahedron() const
Return true if entity is a tetrahedron.
Definition: type.hh:299
constexpr bool isPrism() const
Return true if entity is a prism.
Definition: type.hh:309
constexpr bool isTriangle() const
Return true if entity is a triangle.
Definition: type.hh:289
constexpr bool isLine() const
Return true if entity is a line segment.
Definition: type.hh:284
constexpr bool isQuadrilateral() const
Return true if entity is a quadrilateral.
Definition: type.hh:294
constexpr bool isHexahedron() const
Return true if entity is a hexahedron.
Definition: type.hh:314
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
constexpr GeometryType cube(unsigned int dim)
Returns a GeometryType representing a hypercube of dimension dim.
Definition: type.hh:462
Dune namespace.
Definition: alignedallocator.hh:13
constexpr std::integral_constant< std::size_t, sizeof...(II)> size(std::integer_sequence< T, II... >)
Return the size of the sequence.
Definition: integersequence.hh:75
A unique label for each type of element that can occur in a grid.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Nov 21, 23:30, 2024)